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
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from infrahub.core.constants import GlobalPermissions, InfrahubKind
|
|
6
|
+
from infrahub.core.manager import NodeManager
|
|
7
|
+
from infrahub.exceptions import NodeNotFoundError, ValidationError
|
|
8
|
+
from infrahub.permissions.globals import define_global_permission_from_branch
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from .initialization import GraphqlContext
|
|
12
|
+
from .types.context import ContextInput
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def apply_external_context(graphql_context: GraphqlContext, context_input: ContextInput | None) -> None:
|
|
16
|
+
"""Applies context provided by an external mutation to the GraphQL context"""
|
|
17
|
+
if not context_input or not context_input.account:
|
|
18
|
+
return
|
|
19
|
+
|
|
20
|
+
if graphql_context.active_account_session.account_id == context_input.account.id:
|
|
21
|
+
# If the account_id from the request context is the same as the current account
|
|
22
|
+
# there's no point moving forward with other checks to override the current
|
|
23
|
+
# context we can just continue with what is already there.
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
permission = define_global_permission_from_branch(
|
|
27
|
+
permission=GlobalPermissions.OVERRIDE_CONTEXT, branch_name=graphql_context.branch.name
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
graphql_context.active_permissions.raise_for_permission(permission=permission)
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
account = await NodeManager.get_one_by_id_or_default_filter(
|
|
34
|
+
db=graphql_context.db, id=str(context_input.account.id), kind=InfrahubKind.GENERICACCOUNT
|
|
35
|
+
)
|
|
36
|
+
except NodeNotFoundError as exc:
|
|
37
|
+
raise ValidationError(input_value="Unable to set context for account that doesn't exist") from exc
|
|
38
|
+
|
|
39
|
+
graphql_context.active_account_session.account_id = account.id
|
|
@@ -9,6 +9,7 @@ from infrahub.context import InfrahubContext
|
|
|
9
9
|
from infrahub.core import registry
|
|
10
10
|
from infrahub.core.timestamp import Timestamp
|
|
11
11
|
from infrahub.exceptions import InitializationError
|
|
12
|
+
from infrahub.graphql.resolvers.many_relationship import ManyRelationshipResolver
|
|
12
13
|
from infrahub.graphql.resolvers.single_relationship import SingleRelationshipResolver
|
|
13
14
|
from infrahub.permissions import PermissionManager
|
|
14
15
|
|
|
@@ -36,6 +37,7 @@ class GraphqlContext:
|
|
|
36
37
|
branch: Branch
|
|
37
38
|
types: dict
|
|
38
39
|
single_relationship_resolver: SingleRelationshipResolver
|
|
40
|
+
many_relationship_resolver: ManyRelationshipResolver
|
|
39
41
|
service: InfrahubServices | None = None
|
|
40
42
|
at: Timestamp | None = None
|
|
41
43
|
related_node_ids: set | None = None
|
|
@@ -111,6 +113,7 @@ async def prepare_graphql_params(
|
|
|
111
113
|
db=db,
|
|
112
114
|
branch=branch,
|
|
113
115
|
single_relationship_resolver=SingleRelationshipResolver(),
|
|
116
|
+
many_relationship_resolver=ManyRelationshipResolver(),
|
|
114
117
|
at=Timestamp(at),
|
|
115
118
|
types=gqlm.get_graphql_types(),
|
|
116
119
|
related_node_ids=set(),
|
infrahub/graphql/loaders/node.py
CHANGED
|
@@ -10,6 +10,8 @@ from infrahub.core.node import Node
|
|
|
10
10
|
from infrahub.core.timestamp import Timestamp
|
|
11
11
|
from infrahub.database import InfrahubDatabase
|
|
12
12
|
|
|
13
|
+
from .shared import to_frozen_set
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
@dataclass
|
|
15
17
|
class GetManyParams:
|
|
@@ -68,15 +70,3 @@ class NodeDataLoader(DataLoader[str, Node | None]):
|
|
|
68
70
|
for node_id in keys:
|
|
69
71
|
results.append(nodes_by_id.get(node_id, None))
|
|
70
72
|
return results
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def to_frozen_set(to_freeze: dict[str, Any]) -> frozenset:
|
|
74
|
-
freezing_dict = {}
|
|
75
|
-
for k, v in to_freeze.items():
|
|
76
|
-
if isinstance(v, dict):
|
|
77
|
-
freezing_dict[k] = to_frozen_set(v)
|
|
78
|
-
elif isinstance(v, list | set):
|
|
79
|
-
freezing_dict[k] = frozenset(v)
|
|
80
|
-
else:
|
|
81
|
-
freezing_dict[k] = v
|
|
82
|
-
return frozenset(freezing_dict)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from aiodataloader import DataLoader
|
|
5
|
+
|
|
6
|
+
from infrahub.core.branch.models import Branch
|
|
7
|
+
from infrahub.core.manager import NodeManager
|
|
8
|
+
from infrahub.core.relationship.model import Relationship
|
|
9
|
+
from infrahub.core.schema.relationship_schema import RelationshipSchema
|
|
10
|
+
from infrahub.core.timestamp import Timestamp
|
|
11
|
+
from infrahub.database import InfrahubDatabase
|
|
12
|
+
|
|
13
|
+
from .shared import to_frozen_set
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class QueryPeerParams:
|
|
18
|
+
branch: Branch | str
|
|
19
|
+
source_kind: str
|
|
20
|
+
schema: RelationshipSchema
|
|
21
|
+
filters: dict[str, Any]
|
|
22
|
+
fields: dict | None = None
|
|
23
|
+
at: Timestamp | str | None = None
|
|
24
|
+
branch_agnostic: bool = False
|
|
25
|
+
|
|
26
|
+
def __hash__(self) -> int:
|
|
27
|
+
frozen_fields: frozenset | None = None
|
|
28
|
+
if self.fields:
|
|
29
|
+
frozen_fields = to_frozen_set(self.fields)
|
|
30
|
+
frozen_filters = to_frozen_set(self.filters)
|
|
31
|
+
timestamp = Timestamp(self.at)
|
|
32
|
+
branch = self.branch.name if isinstance(self.branch, Branch) else self.branch
|
|
33
|
+
hash_str = "|".join(
|
|
34
|
+
[
|
|
35
|
+
str(hash(frozen_fields)),
|
|
36
|
+
str(hash(frozen_filters)),
|
|
37
|
+
timestamp.to_string(),
|
|
38
|
+
branch,
|
|
39
|
+
self.schema.name,
|
|
40
|
+
str(self.source_kind),
|
|
41
|
+
str(self.branch_agnostic),
|
|
42
|
+
]
|
|
43
|
+
)
|
|
44
|
+
return hash(hash_str)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class PeerRelationshipsDataLoader(DataLoader[str, list[Relationship]]):
|
|
48
|
+
def __init__(self, db: InfrahubDatabase, query_params: QueryPeerParams, *args: Any, **kwargs: Any) -> None:
|
|
49
|
+
super().__init__(*args, **kwargs)
|
|
50
|
+
self.query_params = query_params
|
|
51
|
+
self.db = db
|
|
52
|
+
|
|
53
|
+
async def batch_load_fn(self, keys: list[Any]) -> list[list[Relationship]]: # pylint: disable=method-hidden
|
|
54
|
+
async with self.db.start_session() as db:
|
|
55
|
+
peer_rels = await NodeManager.query_peers(
|
|
56
|
+
db=db,
|
|
57
|
+
ids=keys,
|
|
58
|
+
source_kind=self.query_params.source_kind,
|
|
59
|
+
schema=self.query_params.schema,
|
|
60
|
+
filters=self.query_params.filters,
|
|
61
|
+
fields=self.query_params.fields,
|
|
62
|
+
at=self.query_params.at,
|
|
63
|
+
branch=self.query_params.branch,
|
|
64
|
+
branch_agnostic=self.query_params.branch_agnostic,
|
|
65
|
+
fetch_peers=True,
|
|
66
|
+
)
|
|
67
|
+
peer_rels_by_node_id: dict[str, list[Relationship]] = {}
|
|
68
|
+
for rel in peer_rels:
|
|
69
|
+
node_id = rel.node_id
|
|
70
|
+
if node_id not in peer_rels_by_node_id:
|
|
71
|
+
peer_rels_by_node_id[node_id] = []
|
|
72
|
+
peer_rels_by_node_id[node_id].append(rel)
|
|
73
|
+
|
|
74
|
+
results = []
|
|
75
|
+
for node_id in keys:
|
|
76
|
+
results.append(peer_rels_by_node_id.get(node_id, []))
|
|
77
|
+
return results
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def to_frozen_set(to_freeze: dict[str, Any]) -> frozenset:
|
|
5
|
+
freezing_dict = {}
|
|
6
|
+
for k, v in to_freeze.items():
|
|
7
|
+
if isinstance(v, dict):
|
|
8
|
+
freezing_dict[k] = to_frozen_set(v)
|
|
9
|
+
elif isinstance(v, list | set):
|
|
10
|
+
freezing_dict[k] = frozenset(v)
|
|
11
|
+
else:
|
|
12
|
+
freezing_dict[k] = v
|
|
13
|
+
return frozenset(freezing_dict)
|
infrahub/graphql/manager.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from typing import TYPE_CHECKING, Any, Iterable
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Iterable
|
|
5
5
|
|
|
6
6
|
import graphene
|
|
7
7
|
|
|
@@ -38,6 +38,7 @@ from .mutations.repository import InfrahubRepositoryMutation
|
|
|
38
38
|
from .mutations.resource_manager import (
|
|
39
39
|
InfrahubNumberPoolMutation,
|
|
40
40
|
)
|
|
41
|
+
from .mutations.webhook import InfrahubWebhookMutation
|
|
41
42
|
from .resolvers.resolver import (
|
|
42
43
|
account_resolver,
|
|
43
44
|
ancestors_resolver,
|
|
@@ -60,6 +61,7 @@ from .types import (
|
|
|
60
61
|
)
|
|
61
62
|
from .types.attribute import BaseAttribute as BaseAttributeType
|
|
62
63
|
from .types.attribute import TextAttributeType
|
|
64
|
+
from .types.context import ContextInput
|
|
63
65
|
from .types.event import EVENT_TYPES
|
|
64
66
|
|
|
65
67
|
if TYPE_CHECKING:
|
|
@@ -74,9 +76,7 @@ class DeleteInput(graphene.InputObjectType):
|
|
|
74
76
|
hfid = graphene.List(of_type=graphene.String, required=False)
|
|
75
77
|
|
|
76
78
|
|
|
77
|
-
GraphQLTypes =
|
|
78
|
-
type[InfrahubMutation], type[BaseAttributeType], type[graphene.Interface], type[graphene.ObjectType]
|
|
79
|
-
]
|
|
79
|
+
GraphQLTypes = type[InfrahubMutation] | type[BaseAttributeType] | type[graphene.Interface] | type[graphene.ObjectType]
|
|
80
80
|
|
|
81
81
|
|
|
82
82
|
class OrderInput(graphene.InputObjectType):
|
|
@@ -512,6 +512,8 @@ class GraphQLSchemaManager:
|
|
|
512
512
|
InfrahubKind.NAMESPACE: InfrahubIPNamespaceMutation,
|
|
513
513
|
InfrahubKind.NUMBERPOOL: InfrahubNumberPoolMutation,
|
|
514
514
|
InfrahubKind.MENUITEM: InfrahubCoreMenuMutation,
|
|
515
|
+
InfrahubKind.STANDARDWEBHOOK: InfrahubWebhookMutation,
|
|
516
|
+
InfrahubKind.CUSTOMWEBHOOK: InfrahubWebhookMutation,
|
|
515
517
|
}
|
|
516
518
|
|
|
517
519
|
if isinstance(node_schema, NodeSchema) and node_schema.is_ip_prefix():
|
|
@@ -642,7 +644,9 @@ class GraphQLSchemaManager:
|
|
|
642
644
|
self.set_type(name=type_name, graphql_type=relationship_property)
|
|
643
645
|
|
|
644
646
|
def generate_graphql_mutations(
|
|
645
|
-
self,
|
|
647
|
+
self,
|
|
648
|
+
schema: NodeSchema | ProfileSchema | TemplateSchema,
|
|
649
|
+
base_class: type[InfrahubMutation],
|
|
646
650
|
) -> GraphqlMutations:
|
|
647
651
|
graphql_mutation_create_input = self.generate_graphql_mutation_create_input(schema)
|
|
648
652
|
graphql_mutation_update_input = self.generate_graphql_mutation_update_input(schema)
|
|
@@ -681,7 +685,7 @@ class GraphQLSchemaManager:
|
|
|
681
685
|
slug = InputField(StringAttributeCreate, required=True)
|
|
682
686
|
description = InputField(StringAttributeCreate, required=False)
|
|
683
687
|
"""
|
|
684
|
-
attrs: dict[str,
|
|
688
|
+
attrs: dict[str, graphene.String | graphene.InputField] = {"id": graphene.String(required=False)}
|
|
685
689
|
|
|
686
690
|
for attr in schema.attributes:
|
|
687
691
|
if attr.read_only:
|
|
@@ -717,7 +721,7 @@ class GraphQLSchemaManager:
|
|
|
717
721
|
slug = InputField(StringAttributeUpdate, required=False)
|
|
718
722
|
description = InputField(StringAttributeUpdate, required=False)
|
|
719
723
|
"""
|
|
720
|
-
attrs: dict[str,
|
|
724
|
+
attrs: dict[str, graphene.String | graphene.InputField] = {
|
|
721
725
|
"id": graphene.String(required=False),
|
|
722
726
|
"hfid": graphene.List(of_type=graphene.String, required=False),
|
|
723
727
|
}
|
|
@@ -758,7 +762,7 @@ class GraphQLSchemaManager:
|
|
|
758
762
|
slug = InputField(StringAttributeUpdate, required=True)
|
|
759
763
|
description = InputField(StringAttributeUpdate, required=False)
|
|
760
764
|
"""
|
|
761
|
-
attrs: dict[str,
|
|
765
|
+
attrs: dict[str, graphene.String | graphene.InputField] = {
|
|
762
766
|
"id": graphene.String(required=False),
|
|
763
767
|
"hfid": graphene.List(of_type=graphene.String, required=False),
|
|
764
768
|
}
|
|
@@ -809,9 +813,7 @@ class GraphQLSchemaManager:
|
|
|
809
813
|
meta_attrs: dict[str, Any] = {"schema": schema, "name": name, "description": schema.description}
|
|
810
814
|
main_attrs["Meta"] = type("Meta", (object,), meta_attrs)
|
|
811
815
|
|
|
812
|
-
args_attrs = {
|
|
813
|
-
"data": input_type(required=True),
|
|
814
|
-
}
|
|
816
|
+
args_attrs = {"data": input_type(required=True), "context": ContextInput(required=False)}
|
|
815
817
|
main_attrs["Arguments"] = type("Arguments", (object,), args_attrs)
|
|
816
818
|
|
|
817
819
|
return type(name, (base_class,), main_attrs)
|
|
@@ -832,9 +834,7 @@ class GraphQLSchemaManager:
|
|
|
832
834
|
meta_attrs: dict[str, Any] = {"schema": schema, "name": name, "description": schema.description}
|
|
833
835
|
main_attrs["Meta"] = type("Meta", (object,), meta_attrs)
|
|
834
836
|
|
|
835
|
-
args_attrs = {
|
|
836
|
-
"data": input_type(required=True),
|
|
837
|
-
}
|
|
837
|
+
args_attrs = {"data": input_type(required=True), "context": ContextInput(required=False)}
|
|
838
838
|
main_attrs["Arguments"] = type("Arguments", (object,), args_attrs)
|
|
839
839
|
|
|
840
840
|
return type(name, (base_class,), main_attrs)
|
|
@@ -851,16 +851,14 @@ class GraphQLSchemaManager:
|
|
|
851
851
|
meta_attrs = {"schema": schema, "name": name, "description": schema.description}
|
|
852
852
|
main_attrs["Meta"] = type("Meta", (object,), meta_attrs)
|
|
853
853
|
|
|
854
|
-
args_attrs: dict[str, Any] = {
|
|
855
|
-
"data": DeleteInput(required=True),
|
|
856
|
-
}
|
|
854
|
+
args_attrs: dict[str, Any] = {"data": DeleteInput(required=True), "context": ContextInput(required=False)}
|
|
857
855
|
main_attrs["Arguments"] = type("Arguments", (object,), args_attrs)
|
|
858
856
|
|
|
859
857
|
return type(name, (base_class,), main_attrs)
|
|
860
858
|
|
|
861
859
|
def generate_filters(
|
|
862
860
|
self, schema: MainSchemaTypes, top_level: bool = False, include_properties: bool = True
|
|
863
|
-
) -> dict[str,
|
|
861
|
+
) -> dict[str, graphene.Scalar | graphene.List]:
|
|
864
862
|
"""Generate the GraphQL filters for a given Schema object.
|
|
865
863
|
|
|
866
864
|
The generated filter will be different if we are at the top_level (query)
|
|
@@ -925,7 +923,7 @@ class GraphQLSchemaManager:
|
|
|
925
923
|
self,
|
|
926
924
|
schema: MainSchemaTypes,
|
|
927
925
|
node: type[InfrahubObject],
|
|
928
|
-
relation_property:
|
|
926
|
+
relation_property: type[InfrahubObject] | None = None,
|
|
929
927
|
populate_cache: bool = False,
|
|
930
928
|
) -> type[InfrahubObject]:
|
|
931
929
|
"""Generate a edged GraphQL object Type from a Infrahub NodeSchema for pagination."""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING, Any
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
4
|
|
|
5
5
|
from graphene import InputObjectType, Mutation
|
|
6
6
|
from typing_extensions import Self
|
|
@@ -28,7 +28,7 @@ class InfrahubArtifactDefinitionMutation(InfrahubMutationMixin, Mutation):
|
|
|
28
28
|
def __init_subclass_with_meta__(
|
|
29
29
|
cls,
|
|
30
30
|
schema: NodeSchema,
|
|
31
|
-
_meta:
|
|
31
|
+
_meta: Any | None = None,
|
|
32
32
|
**options: dict[str, Any],
|
|
33
33
|
) -> None:
|
|
34
34
|
# Make sure schema is a valid NodeSchema Node Class
|
|
@@ -48,7 +48,7 @@ class InfrahubArtifactDefinitionMutation(InfrahubMutationMixin, Mutation):
|
|
|
48
48
|
info: GraphQLResolveInfo,
|
|
49
49
|
data: InputObjectType,
|
|
50
50
|
branch: Branch,
|
|
51
|
-
database:
|
|
51
|
+
database: InfrahubDatabase | None = None, # noqa: ARG003
|
|
52
52
|
) -> tuple[Node, Self]:
|
|
53
53
|
graphql_context: GraphqlContext = info.context
|
|
54
54
|
|
|
@@ -74,8 +74,8 @@ class InfrahubArtifactDefinitionMutation(InfrahubMutationMixin, Mutation):
|
|
|
74
74
|
info: GraphQLResolveInfo,
|
|
75
75
|
data: InputObjectType,
|
|
76
76
|
branch: Branch,
|
|
77
|
-
database:
|
|
78
|
-
node:
|
|
77
|
+
database: InfrahubDatabase | None = None, # noqa: ARG003
|
|
78
|
+
node: Node | None = None, # noqa: ARG003
|
|
79
79
|
) -> tuple[Node, Self]:
|
|
80
80
|
graphql_context: GraphqlContext = info.context
|
|
81
81
|
|
|
@@ -9,6 +9,8 @@ from typing_extensions import Self
|
|
|
9
9
|
|
|
10
10
|
from infrahub.core.branch import Branch
|
|
11
11
|
from infrahub.database import retry_db_transaction
|
|
12
|
+
from infrahub.graphql.context import apply_external_context
|
|
13
|
+
from infrahub.graphql.types.context import ContextInput
|
|
12
14
|
from infrahub.log import get_logger
|
|
13
15
|
from infrahub.workflows.catalogue import (
|
|
14
16
|
BRANCH_CREATE,
|
|
@@ -44,6 +46,7 @@ class BranchCreateInput(InputObjectType):
|
|
|
44
46
|
class BranchCreate(Mutation):
|
|
45
47
|
class Arguments:
|
|
46
48
|
data = BranchCreateInput(required=True)
|
|
49
|
+
context = ContextInput(required=False)
|
|
47
50
|
background_execution = Boolean(required=False, deprecation_reason="Please use `wait_until_completion` instead")
|
|
48
51
|
wait_until_completion = Boolean(required=False)
|
|
49
52
|
|
|
@@ -58,6 +61,7 @@ class BranchCreate(Mutation):
|
|
|
58
61
|
root: dict, # noqa: ARG003
|
|
59
62
|
info: GraphQLResolveInfo,
|
|
60
63
|
data: BranchCreateInput,
|
|
64
|
+
context: ContextInput | None = None,
|
|
61
65
|
background_execution: bool = False,
|
|
62
66
|
wait_until_completion: bool = True,
|
|
63
67
|
) -> Self:
|
|
@@ -65,6 +69,7 @@ class BranchCreate(Mutation):
|
|
|
65
69
|
task: dict | None = None
|
|
66
70
|
|
|
67
71
|
model = BranchCreateModel(**data)
|
|
72
|
+
await apply_external_context(graphql_context=graphql_context, context_input=context)
|
|
68
73
|
|
|
69
74
|
if background_execution or not wait_until_completion:
|
|
70
75
|
workflow = await graphql_context.active_service.workflow.submit_workflow(
|
|
@@ -96,6 +101,7 @@ class BranchUpdateInput(InputObjectType):
|
|
|
96
101
|
class BranchDelete(Mutation):
|
|
97
102
|
class Arguments:
|
|
98
103
|
data = BranchNameInput(required=True)
|
|
104
|
+
context = ContextInput(required=False)
|
|
99
105
|
wait_until_completion = Boolean(required=False)
|
|
100
106
|
|
|
101
107
|
ok = Boolean()
|
|
@@ -107,10 +113,12 @@ class BranchDelete(Mutation):
|
|
|
107
113
|
root: dict, # noqa: ARG003
|
|
108
114
|
info: GraphQLResolveInfo,
|
|
109
115
|
data: BranchNameInput,
|
|
116
|
+
context: ContextInput | None = None,
|
|
110
117
|
wait_until_completion: bool = True,
|
|
111
118
|
) -> Self:
|
|
112
119
|
graphql_context: GraphqlContext = info.context
|
|
113
120
|
obj = await Branch.get_by_name(db=graphql_context.db, name=str(data.name))
|
|
121
|
+
await apply_external_context(graphql_context=graphql_context, context_input=context)
|
|
114
122
|
|
|
115
123
|
if wait_until_completion:
|
|
116
124
|
await graphql_context.active_service.workflow.execute_workflow(
|
|
@@ -127,15 +135,23 @@ class BranchDelete(Mutation):
|
|
|
127
135
|
class BranchUpdate(Mutation):
|
|
128
136
|
class Arguments:
|
|
129
137
|
data = BranchUpdateInput(required=True)
|
|
138
|
+
context = ContextInput(required=False)
|
|
130
139
|
|
|
131
140
|
ok = Boolean()
|
|
132
141
|
|
|
133
142
|
@classmethod
|
|
134
143
|
@retry_db_transaction(name="branch_update")
|
|
135
|
-
async def mutate(
|
|
144
|
+
async def mutate(
|
|
145
|
+
cls,
|
|
146
|
+
root: dict, # noqa: ARG003
|
|
147
|
+
info: GraphQLResolveInfo,
|
|
148
|
+
data: BranchNameInput,
|
|
149
|
+
context: ContextInput | None = None,
|
|
150
|
+
) -> Self:
|
|
136
151
|
graphql_context: GraphqlContext = info.context
|
|
137
152
|
|
|
138
153
|
obj = await Branch.get_by_name(db=graphql_context.db, name=data["name"])
|
|
154
|
+
await apply_external_context(graphql_context=graphql_context, context_input=context)
|
|
139
155
|
|
|
140
156
|
to_extract = ["description"]
|
|
141
157
|
for field_name in to_extract:
|
|
@@ -151,6 +167,7 @@ class BranchUpdate(Mutation):
|
|
|
151
167
|
class BranchRebase(Mutation):
|
|
152
168
|
class Arguments:
|
|
153
169
|
data = BranchNameInput(required=True)
|
|
170
|
+
context = ContextInput(required=False)
|
|
154
171
|
wait_until_completion = Boolean(required=False)
|
|
155
172
|
|
|
156
173
|
ok = Boolean()
|
|
@@ -163,11 +180,13 @@ class BranchRebase(Mutation):
|
|
|
163
180
|
root: dict, # noqa: ARG003
|
|
164
181
|
info: GraphQLResolveInfo,
|
|
165
182
|
data: BranchNameInput,
|
|
183
|
+
context: ContextInput | None = None,
|
|
166
184
|
wait_until_completion: bool = True,
|
|
167
185
|
) -> Self:
|
|
168
186
|
graphql_context: GraphqlContext = info.context
|
|
169
187
|
|
|
170
188
|
obj = await Branch.get_by_name(db=graphql_context.db, name=str(data.name))
|
|
189
|
+
await apply_external_context(graphql_context=graphql_context, context_input=context)
|
|
171
190
|
task: dict | None = None
|
|
172
191
|
|
|
173
192
|
if wait_until_completion:
|
|
@@ -192,6 +211,7 @@ class BranchRebase(Mutation):
|
|
|
192
211
|
class BranchValidate(Mutation):
|
|
193
212
|
class Arguments:
|
|
194
213
|
data = BranchNameInput(required=True)
|
|
214
|
+
context = ContextInput(required=False)
|
|
195
215
|
wait_until_completion = Boolean(required=False)
|
|
196
216
|
|
|
197
217
|
ok = Boolean()
|
|
@@ -205,11 +225,13 @@ class BranchValidate(Mutation):
|
|
|
205
225
|
root: dict, # noqa: ARG003
|
|
206
226
|
info: GraphQLResolveInfo,
|
|
207
227
|
data: BranchNameInput,
|
|
228
|
+
context: ContextInput | None = None,
|
|
208
229
|
wait_until_completion: bool = True,
|
|
209
230
|
) -> Self:
|
|
210
231
|
graphql_context: GraphqlContext = info.context
|
|
211
232
|
|
|
212
233
|
obj = await Branch.get_by_name(db=graphql_context.db, name=str(data.name))
|
|
234
|
+
await apply_external_context(graphql_context=graphql_context, context_input=context)
|
|
213
235
|
task: dict | None = None
|
|
214
236
|
ok = True
|
|
215
237
|
|
|
@@ -231,6 +253,7 @@ class BranchValidate(Mutation):
|
|
|
231
253
|
class BranchMerge(Mutation):
|
|
232
254
|
class Arguments:
|
|
233
255
|
data = BranchNameInput(required=True)
|
|
256
|
+
context = ContextInput(required=False)
|
|
234
257
|
wait_until_completion = Boolean(required=False)
|
|
235
258
|
|
|
236
259
|
ok = Boolean()
|
|
@@ -243,11 +266,13 @@ class BranchMerge(Mutation):
|
|
|
243
266
|
root: dict, # noqa: ARG003
|
|
244
267
|
info: GraphQLResolveInfo,
|
|
245
268
|
data: BranchNameInput,
|
|
269
|
+
context: ContextInput | None = None,
|
|
246
270
|
wait_until_completion: bool = True,
|
|
247
271
|
) -> Self:
|
|
248
272
|
branch_name = data["name"]
|
|
249
273
|
task: dict | None = None
|
|
250
274
|
graphql_context: GraphqlContext = info.context
|
|
275
|
+
await apply_external_context(graphql_context=graphql_context, context_input=context)
|
|
251
276
|
|
|
252
277
|
if wait_until_completion:
|
|
253
278
|
await graphql_context.active_service.workflow.execute_workflow(
|
|
@@ -5,13 +5,15 @@ from typing import TYPE_CHECKING, Any
|
|
|
5
5
|
from graphene import Boolean, InputObjectType, Mutation, String
|
|
6
6
|
|
|
7
7
|
from infrahub.core.account import ObjectPermission
|
|
8
|
-
from infrahub.core.constants import ComputedAttributeKind,
|
|
8
|
+
from infrahub.core.constants import ComputedAttributeKind, PermissionAction, PermissionDecision
|
|
9
9
|
from infrahub.core.manager import NodeManager
|
|
10
10
|
from infrahub.core.registry import registry
|
|
11
11
|
from infrahub.database import retry_db_transaction
|
|
12
12
|
from infrahub.events import EventMeta
|
|
13
|
-
from infrahub.events.node_action import
|
|
13
|
+
from infrahub.events.node_action import NodeUpdatedEvent
|
|
14
14
|
from infrahub.exceptions import NodeNotFoundError, ValidationError
|
|
15
|
+
from infrahub.graphql.context import apply_external_context
|
|
16
|
+
from infrahub.graphql.types.context import ContextInput
|
|
15
17
|
from infrahub.log import get_log_data
|
|
16
18
|
from infrahub.worker import WORKER_IDENTITY
|
|
17
19
|
|
|
@@ -31,6 +33,7 @@ class InfrahubComputedAttributeUpdateInput(InputObjectType):
|
|
|
31
33
|
class UpdateComputedAttribute(Mutation):
|
|
32
34
|
class Arguments:
|
|
33
35
|
data = InfrahubComputedAttributeUpdateInput(required=True)
|
|
36
|
+
context = ContextInput(required=False)
|
|
34
37
|
|
|
35
38
|
ok = Boolean()
|
|
36
39
|
|
|
@@ -41,6 +44,7 @@ class UpdateComputedAttribute(Mutation):
|
|
|
41
44
|
_: dict,
|
|
42
45
|
info: GraphQLResolveInfo,
|
|
43
46
|
data: InfrahubComputedAttributeUpdateInput,
|
|
47
|
+
context: ContextInput | None = None,
|
|
44
48
|
) -> UpdateComputedAttribute:
|
|
45
49
|
graphql_context: GraphqlContext = info.context
|
|
46
50
|
node_schema = registry.schema.get_node_schema(
|
|
@@ -63,6 +67,7 @@ class UpdateComputedAttribute(Mutation):
|
|
|
63
67
|
else PermissionDecision.ALLOW_OTHER.value,
|
|
64
68
|
)
|
|
65
69
|
)
|
|
70
|
+
await apply_external_context(graphql_context=graphql_context, context_input=context)
|
|
66
71
|
|
|
67
72
|
if not (
|
|
68
73
|
target_node := await NodeManager.get_one(
|
|
@@ -90,12 +95,11 @@ class UpdateComputedAttribute(Mutation):
|
|
|
90
95
|
log_data = get_log_data()
|
|
91
96
|
request_id = log_data.get("request_id", "")
|
|
92
97
|
|
|
93
|
-
event =
|
|
98
|
+
event = NodeUpdatedEvent(
|
|
94
99
|
kind=node_schema.kind,
|
|
95
100
|
node_id=target_node.get_id(),
|
|
96
|
-
|
|
101
|
+
changelog=target_node.node_changelog.model_dump(),
|
|
97
102
|
fields=[str(data.attribute)],
|
|
98
|
-
action=MutationAction.UPDATED,
|
|
99
103
|
meta=EventMeta(
|
|
100
104
|
context=graphql_context.get_context(),
|
|
101
105
|
initiator_id=WORKER_IDENTITY,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
|
-
from graphene import Boolean, DateTime, InputObjectType, Mutation, String
|
|
3
|
+
from graphene import Boolean, DateTime, Field, InputObjectType, Mutation, String
|
|
4
4
|
from graphql import GraphQLResolveInfo
|
|
5
5
|
|
|
6
6
|
from infrahub.core import registry
|
|
@@ -9,11 +9,14 @@ from infrahub.core.diff.model.path import NameTrackingId
|
|
|
9
9
|
from infrahub.core.diff.models import RequestDiffUpdate
|
|
10
10
|
from infrahub.core.diff.repository.repository import DiffRepository
|
|
11
11
|
from infrahub.core.timestamp import Timestamp
|
|
12
|
-
from infrahub.database import retry_db_transaction
|
|
13
12
|
from infrahub.dependencies.registry import get_component_registry
|
|
14
13
|
from infrahub.exceptions import ValidationError
|
|
14
|
+
from infrahub.graphql.context import apply_external_context
|
|
15
|
+
from infrahub.graphql.types.context import ContextInput
|
|
15
16
|
from infrahub.workflows.catalogue import DIFF_UPDATE
|
|
16
17
|
|
|
18
|
+
from ..types.task import TaskInfo
|
|
19
|
+
|
|
17
20
|
if TYPE_CHECKING:
|
|
18
21
|
from ..initialization import GraphqlContext
|
|
19
22
|
|
|
@@ -23,24 +26,32 @@ class DiffUpdateInput(InputObjectType):
|
|
|
23
26
|
name = String(required=False)
|
|
24
27
|
from_time = DateTime(required=False)
|
|
25
28
|
to_time = DateTime(required=False)
|
|
26
|
-
wait_for_completion = Boolean(required=False)
|
|
29
|
+
wait_for_completion = Boolean(required=False, deprecation_reason="Please use `wait_until_completion` instead")
|
|
27
30
|
|
|
28
31
|
|
|
29
32
|
class DiffUpdateMutation(Mutation):
|
|
30
33
|
class Arguments:
|
|
31
34
|
data = DiffUpdateInput(required=True)
|
|
35
|
+
context = ContextInput(required=False)
|
|
36
|
+
wait_until_completion = Boolean(required=False)
|
|
32
37
|
|
|
33
38
|
ok = Boolean()
|
|
39
|
+
task = Field(TaskInfo, required=False)
|
|
34
40
|
|
|
35
41
|
@classmethod
|
|
36
|
-
@retry_db_transaction(name="diff_update")
|
|
37
42
|
async def mutate(
|
|
38
43
|
cls,
|
|
39
44
|
root: dict, # noqa: ARG003
|
|
40
45
|
info: GraphQLResolveInfo,
|
|
41
46
|
data: DiffUpdateInput,
|
|
42
|
-
|
|
47
|
+
context: ContextInput | None = None,
|
|
48
|
+
wait_until_completion: bool = False,
|
|
49
|
+
) -> dict[str, bool | dict[str, str]]:
|
|
43
50
|
graphql_context: GraphqlContext = info.context
|
|
51
|
+
await apply_external_context(graphql_context=graphql_context, context_input=context)
|
|
52
|
+
|
|
53
|
+
if data.wait_for_completion is True:
|
|
54
|
+
wait_until_completion = True
|
|
44
55
|
|
|
45
56
|
from_timestamp_str = DateTime.serialize(data.from_time) if data.from_time else None
|
|
46
57
|
to_timestamp_str = DateTime.serialize(data.to_time) if data.to_time else None
|
|
@@ -55,11 +66,11 @@ class DiffUpdateMutation(Mutation):
|
|
|
55
66
|
)
|
|
56
67
|
|
|
57
68
|
tracking_id = NameTrackingId(name=data.name)
|
|
58
|
-
|
|
69
|
+
existing_diffs_metadatas = await diff_repository.get_roots_metadata(
|
|
59
70
|
diff_branch_names=[diff_branch.name], base_branch_names=[base_branch.name], tracking_id=tracking_id
|
|
60
71
|
)
|
|
61
|
-
if
|
|
62
|
-
metadata =
|
|
72
|
+
if existing_diffs_metadatas:
|
|
73
|
+
metadata = existing_diffs_metadatas[0]
|
|
63
74
|
from_time = Timestamp(from_timestamp_str) if from_timestamp_str else None
|
|
64
75
|
to_time = Timestamp(to_timestamp_str) if to_timestamp_str else None
|
|
65
76
|
branched_from_timestamp = Timestamp(diff_branch.get_branched_from())
|
|
@@ -70,7 +81,7 @@ class DiffUpdateMutation(Mutation):
|
|
|
70
81
|
if to_time and to_time < metadata.to_time:
|
|
71
82
|
raise ValidationError(f"to_time must be null or greater than or equal to {metadata.to_time}")
|
|
72
83
|
|
|
73
|
-
if
|
|
84
|
+
if wait_until_completion is True:
|
|
74
85
|
diff_coordinator = await component_registry.get_component(
|
|
75
86
|
DiffCoordinator, db=graphql_context.db, branch=diff_branch
|
|
76
87
|
)
|
|
@@ -91,8 +102,9 @@ class DiffUpdateMutation(Mutation):
|
|
|
91
102
|
to_time=to_timestamp_str,
|
|
92
103
|
)
|
|
93
104
|
if graphql_context.service:
|
|
94
|
-
await graphql_context.service.workflow.submit_workflow(
|
|
95
|
-
workflow=DIFF_UPDATE,
|
|
105
|
+
workflow = await graphql_context.service.workflow.submit_workflow(
|
|
106
|
+
workflow=DIFF_UPDATE, parameters={"model": model}
|
|
96
107
|
)
|
|
108
|
+
return {"ok": True, "task": {"id": str(workflow.id)}}
|
|
97
109
|
|
|
98
110
|
return {"ok": True}
|
|
@@ -11,7 +11,9 @@ from infrahub.core.manager import NodeManager
|
|
|
11
11
|
from infrahub.database import retry_db_transaction
|
|
12
12
|
from infrahub.dependencies.registry import get_component_registry
|
|
13
13
|
from infrahub.exceptions import ProcessingError
|
|
14
|
+
from infrahub.graphql.context import apply_external_context
|
|
14
15
|
from infrahub.graphql.enums import ConflictSelection as GraphQlConflictSelection
|
|
16
|
+
from infrahub.graphql.types.context import ContextInput
|
|
15
17
|
|
|
16
18
|
if TYPE_CHECKING:
|
|
17
19
|
from graphql import GraphQLResolveInfo
|
|
@@ -29,6 +31,7 @@ class ResolveDiffConflictInput(InputObjectType):
|
|
|
29
31
|
class ResolveDiffConflict(Mutation):
|
|
30
32
|
class Arguments:
|
|
31
33
|
data = ResolveDiffConflictInput(required=True)
|
|
34
|
+
context = ContextInput(required=False)
|
|
32
35
|
|
|
33
36
|
ok = Boolean()
|
|
34
37
|
|
|
@@ -39,8 +42,10 @@ class ResolveDiffConflict(Mutation):
|
|
|
39
42
|
root: dict, # noqa: ARG003
|
|
40
43
|
info: GraphQLResolveInfo,
|
|
41
44
|
data: ResolveDiffConflictInput,
|
|
45
|
+
context: ContextInput | None = None,
|
|
42
46
|
) -> ResolveDiffConflict:
|
|
43
47
|
graphql_context: GraphqlContext = info.context
|
|
48
|
+
await apply_external_context(graphql_context=graphql_context, context_input=context)
|
|
44
49
|
|
|
45
50
|
component_registry = get_component_registry()
|
|
46
51
|
diff_repo = await component_registry.get_component(
|