infrahub-server 1.1.6__py3-none-any.whl → 1.2.0rc0__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/artifact.py +16 -4
- infrahub/api/dependencies.py +8 -0
- infrahub/api/oauth2.py +0 -1
- infrahub/api/oidc.py +0 -1
- infrahub/api/query.py +18 -7
- infrahub/api/schema.py +32 -6
- infrahub/api/transformation.py +12 -5
- infrahub/{message_bus/messages/check_artifact_create.py → artifacts/models.py} +2 -4
- infrahub/{message_bus/operations/check/artifact.py → artifacts/tasks.py} +26 -25
- infrahub/cli/__init__.py +0 -2
- infrahub/cli/db.py +6 -7
- infrahub/cli/events.py +8 -3
- infrahub/cli/git_agent.py +9 -7
- infrahub/cli/tasks.py +4 -6
- infrahub/computed_attribute/tasks.py +63 -17
- infrahub/computed_attribute/triggers.py +90 -0
- infrahub/config.py +1 -1
- infrahub/context.py +39 -0
- infrahub/core/account.py +5 -8
- infrahub/core/attribute.py +53 -21
- infrahub/core/branch/models.py +4 -4
- infrahub/core/branch/tasks.py +89 -130
- infrahub/core/changelog/__init__.py +0 -0
- infrahub/core/changelog/diff.py +232 -0
- infrahub/core/changelog/models.py +488 -0
- infrahub/core/constants/__init__.py +19 -2
- infrahub/core/constants/infrahubkind.py +1 -0
- infrahub/core/diff/combiner.py +12 -8
- infrahub/core/diff/coordinator.py +49 -70
- infrahub/core/diff/data_check_synchronizer.py +86 -7
- infrahub/core/diff/enricher/aggregated.py +3 -3
- infrahub/core/diff/enricher/cardinality_one.py +2 -7
- infrahub/core/diff/enricher/hierarchy.py +5 -3
- infrahub/core/diff/enricher/labels.py +14 -4
- infrahub/core/diff/enricher/path_identifier.py +3 -9
- infrahub/core/diff/enricher/summary_counts.py +3 -1
- infrahub/core/diff/merger/merger.py +8 -4
- infrahub/core/diff/model/path.py +47 -29
- infrahub/core/diff/query/all_conflicts.py +6 -3
- infrahub/core/diff/query/artifact.py +1 -1
- infrahub/core/diff/query/delete_query.py +1 -1
- infrahub/core/diff/query/diff_get.py +3 -2
- infrahub/core/diff/query/diff_summary.py +1 -1
- infrahub/core/diff/query/field_specifiers.py +3 -1
- infrahub/core/diff/query/field_summary.py +3 -2
- infrahub/core/diff/query/filters.py +12 -1
- infrahub/core/diff/query/get_conflict_query.py +1 -1
- infrahub/core/diff/query/has_conflicts_query.py +6 -3
- infrahub/core/diff/query/merge.py +3 -3
- infrahub/core/diff/query/{drop_tracking_id.py → merge_tracking_id.py} +4 -4
- infrahub/core/diff/query/roots_metadata.py +9 -2
- infrahub/core/diff/query/save.py +151 -66
- infrahub/core/diff/query/summary_counts_enricher.py +220 -0
- infrahub/core/diff/query/time_range_query.py +3 -2
- infrahub/core/diff/query/update_conflict_query.py +1 -1
- infrahub/core/diff/query_parser.py +49 -24
- infrahub/core/diff/repository/deserializer.py +24 -25
- infrahub/core/diff/repository/repository.py +76 -20
- infrahub/core/diff/tasks.py +9 -8
- infrahub/core/enums.py +1 -1
- infrahub/core/integrity/object_conflict/conflict_recorder.py +1 -1
- infrahub/core/ipam/reconciler.py +1 -1
- infrahub/core/ipam/tasks.py +2 -3
- infrahub/core/manager.py +18 -13
- infrahub/core/merge.py +5 -2
- infrahub/core/migrations/graph/m001_add_version_to_graph.py +1 -1
- infrahub/core/migrations/graph/m002_attribute_is_default.py +2 -2
- infrahub/core/migrations/graph/m003_relationship_parent_optional.py +2 -2
- infrahub/core/migrations/graph/m004_add_attr_documentation.py +1 -1
- infrahub/core/migrations/graph/m005_add_rel_read_only.py +1 -1
- infrahub/core/migrations/graph/m006_add_rel_on_delete.py +1 -1
- infrahub/core/migrations/graph/m007_add_rel_allow_override.py +1 -1
- infrahub/core/migrations/graph/m008_add_human_friendly_id.py +1 -1
- infrahub/core/migrations/graph/m009_add_generate_profile_attr.py +1 -1
- infrahub/core/migrations/graph/m010_add_generate_profile_attr_generic.py +1 -1
- infrahub/core/migrations/graph/m011_remove_profile_relationship_schema.py +2 -2
- infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -23
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -11
- infrahub/core/migrations/graph/m014_remove_index_attr_value.py +2 -2
- infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
- infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
- infrahub/core/migrations/graph/m017_add_core_profile.py +1 -1
- infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -2
- infrahub/core/migrations/query/attribute_add.py +1 -1
- infrahub/core/migrations/query/attribute_rename.py +1 -1
- infrahub/core/migrations/query/delete_element_in_schema.py +1 -1
- infrahub/core/migrations/query/node_duplicate.py +1 -1
- infrahub/core/migrations/query/relationship_duplicate.py +1 -1
- infrahub/core/migrations/query/schema_attribute_update.py +1 -1
- infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
- infrahub/core/migrations/schema/node_remove.py +1 -1
- infrahub/core/migrations/schema/tasks.py +5 -5
- infrahub/core/migrations/shared.py +4 -4
- infrahub/core/models.py +7 -8
- infrahub/core/node/__init__.py +161 -40
- infrahub/core/node/base.py +1 -1
- infrahub/core/node/constraints/grouped_uniqueness.py +9 -2
- infrahub/core/node/delete_validator.py +4 -4
- infrahub/core/node/ipam.py +13 -8
- infrahub/core/node/permissions.py +4 -0
- infrahub/core/node/resource_manager/ip_prefix_pool.py +8 -5
- infrahub/core/node/standard.py +3 -5
- infrahub/core/property.py +1 -1
- infrahub/core/protocols.py +4 -0
- infrahub/core/protocols_base.py +4 -2
- infrahub/core/query/__init__.py +2 -5
- infrahub/core/query/attribute.py +9 -9
- infrahub/core/query/branch.py +5 -5
- infrahub/core/query/delete.py +1 -1
- infrahub/core/query/diff.py +45 -7
- infrahub/core/query/ipam.py +4 -4
- infrahub/core/query/node.py +19 -14
- infrahub/core/query/relationship.py +10 -11
- infrahub/core/query/resource_manager.py +13 -11
- infrahub/core/query/standard_node.py +6 -6
- infrahub/core/query/task.py +3 -3
- infrahub/core/query/task_log.py +1 -1
- infrahub/core/query/utils.py +5 -5
- infrahub/core/registry.py +0 -2
- infrahub/core/relationship/constraints/count.py +1 -1
- infrahub/core/relationship/constraints/peer_kind.py +1 -1
- infrahub/core/relationship/model.py +66 -26
- infrahub/core/schema/__init__.py +6 -4
- infrahub/core/schema/basenode_schema.py +1 -3
- infrahub/core/schema/definitions/core.py +14 -2
- infrahub/core/schema/definitions/internal.py +16 -0
- infrahub/core/schema/generated/genericnode_schema.py +5 -0
- infrahub/core/schema/generated/node_schema.py +5 -0
- infrahub/core/schema/generic_schema.py +5 -1
- infrahub/core/schema/manager.py +45 -42
- infrahub/core/schema/node_schema.py +4 -0
- infrahub/core/schema/profile_schema.py +4 -0
- infrahub/core/schema/relationship_schema.py +2 -2
- infrahub/core/schema/schema_branch.py +248 -14
- infrahub/core/schema/template_schema.py +36 -0
- infrahub/core/task/user_task.py +7 -5
- infrahub/core/timestamp.py +1 -1
- infrahub/core/utils.py +3 -2
- infrahub/core/validators/attribute/choices.py +1 -1
- infrahub/core/validators/attribute/enum.py +1 -1
- infrahub/core/validators/attribute/kind.py +1 -1
- infrahub/core/validators/attribute/length.py +1 -1
- infrahub/core/validators/attribute/optional.py +1 -1
- infrahub/core/validators/attribute/regex.py +1 -1
- infrahub/core/validators/attribute/unique.py +1 -1
- infrahub/core/validators/checks_runner.py +37 -0
- infrahub/core/validators/node/generate_profile.py +1 -1
- infrahub/core/validators/node/hierarchy.py +1 -1
- infrahub/core/validators/query.py +1 -1
- infrahub/core/validators/relationship/count.py +1 -1
- infrahub/core/validators/relationship/optional.py +1 -1
- infrahub/core/validators/relationship/peer.py +1 -1
- infrahub/core/validators/tasks.py +8 -6
- infrahub/core/validators/uniqueness/query.py +20 -17
- infrahub/database/__init__.py +15 -2
- infrahub/database/memgraph.py +1 -1
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +0 -2
- infrahub/dependencies/builder/diff/combiner.py +1 -1
- infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
- infrahub/dependencies/builder/diff/coordinator.py +0 -2
- infrahub/dependencies/builder/diff/deserializer.py +1 -1
- infrahub/dependencies/builder/diff/enricher/summary_counts.py +1 -1
- infrahub/events/branch_action.py +47 -21
- infrahub/events/group_action.py +73 -0
- infrahub/events/models.py +159 -51
- infrahub/events/node_action.py +74 -8
- infrahub/events/repository_action.py +8 -8
- infrahub/events/schema_action.py +21 -8
- infrahub/generators/tasks.py +12 -13
- infrahub/git/base.py +3 -5
- infrahub/git/constants.py +0 -1
- infrahub/git/integrator.py +36 -35
- infrahub/git/repository.py +7 -8
- infrahub/git/tasks.py +43 -107
- infrahub/git_credential/helper.py +2 -3
- infrahub/graphql/analyzer.py +572 -11
- infrahub/graphql/app.py +34 -26
- infrahub/graphql/auth/query_permission_checker/anonymous_checker.py +5 -5
- infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +4 -4
- infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +4 -4
- infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +28 -35
- infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -5
- infrahub/graphql/enums.py +1 -1
- infrahub/graphql/initialization.py +5 -1
- infrahub/graphql/loaders/node.py +2 -2
- infrahub/graphql/manager.py +59 -54
- infrahub/graphql/mutations/account.py +20 -13
- infrahub/graphql/mutations/artifact_definition.py +16 -12
- infrahub/graphql/mutations/branch.py +61 -40
- infrahub/graphql/mutations/computed_attribute.py +19 -13
- infrahub/graphql/mutations/diff.py +37 -9
- infrahub/graphql/mutations/diff_conflict.py +9 -8
- infrahub/graphql/mutations/graphql_query.py +19 -11
- infrahub/graphql/mutations/ipam.py +21 -19
- infrahub/graphql/mutations/main.py +197 -44
- infrahub/graphql/mutations/menu.py +8 -8
- infrahub/graphql/mutations/proposed_change.py +36 -28
- infrahub/graphql/mutations/relationship.py +302 -105
- infrahub/graphql/mutations/repository.py +41 -35
- infrahub/graphql/mutations/resource_manager.py +26 -26
- infrahub/graphql/mutations/schema.py +51 -33
- infrahub/graphql/mutations/tasks.py +16 -10
- infrahub/graphql/parser.py +1 -1
- infrahub/graphql/permissions.py +6 -4
- infrahub/graphql/queries/account.py +22 -18
- infrahub/graphql/queries/branch.py +6 -4
- infrahub/graphql/queries/diff/tree.py +48 -42
- infrahub/graphql/queries/event.py +112 -0
- infrahub/graphql/queries/internal.py +3 -3
- infrahub/graphql/queries/ipam.py +23 -18
- infrahub/graphql/queries/relationship.py +11 -10
- infrahub/graphql/queries/resource_manager.py +43 -27
- infrahub/graphql/queries/search.py +9 -8
- infrahub/graphql/queries/status.py +12 -9
- infrahub/graphql/queries/task.py +11 -9
- infrahub/graphql/resolvers/resolver.py +69 -43
- infrahub/graphql/resolvers/single_relationship.py +16 -10
- infrahub/graphql/schema.py +2 -0
- infrahub/graphql/subscription/__init__.py +1 -1
- infrahub/graphql/subscription/events.py +1 -1
- infrahub/graphql/subscription/graphql_query.py +8 -8
- infrahub/graphql/types/branch.py +2 -2
- infrahub/graphql/types/common.py +6 -1
- infrahub/graphql/types/enums.py +2 -0
- infrahub/graphql/types/event.py +100 -0
- infrahub/graphql/types/interface.py +2 -2
- infrahub/graphql/types/node.py +3 -3
- infrahub/graphql/types/permission.py +2 -2
- infrahub/graphql/types/relationship.py +3 -3
- infrahub/graphql/types/standard_node.py +9 -11
- infrahub/graphql/utils.py +28 -182
- infrahub/groups/tasks.py +2 -3
- infrahub/lock.py +1 -1
- infrahub/menu/constants.py +1 -0
- infrahub/menu/generator.py +14 -3
- infrahub/menu/menu.py +116 -127
- infrahub/menu/models.py +4 -4
- infrahub/message_bus/messages/__init__.py +0 -4
- infrahub/message_bus/messages/event_branch_merge.py +3 -0
- infrahub/message_bus/messages/request_proposedchange_pipeline.py +2 -0
- infrahub/message_bus/operations/__init__.py +3 -5
- infrahub/message_bus/operations/check/__init__.py +2 -2
- infrahub/message_bus/operations/check/generator.py +1 -3
- infrahub/message_bus/operations/check/repository.py +1 -1
- infrahub/message_bus/operations/event/branch.py +7 -3
- infrahub/message_bus/operations/event/schema.py +1 -1
- infrahub/message_bus/operations/finalize/validator.py +1 -1
- infrahub/message_bus/operations/git/file.py +2 -2
- infrahub/message_bus/operations/git/repository.py +1 -1
- infrahub/message_bus/operations/requests/__init__.py +0 -2
- infrahub/message_bus/operations/requests/generator_definition.py +1 -1
- infrahub/message_bus/operations/requests/proposed_change.py +26 -11
- infrahub/message_bus/operations/requests/repository.py +2 -2
- infrahub/message_bus/operations/send/echo.py +1 -1
- infrahub/message_bus/types.py +1 -1
- infrahub/permissions/__init__.py +2 -1
- infrahub/permissions/types.py +26 -0
- infrahub/pools/prefix.py +29 -165
- infrahub/prefect_server/__init__.py +0 -0
- infrahub/prefect_server/app.py +18 -0
- infrahub/prefect_server/database.py +20 -0
- infrahub/prefect_server/events.py +28 -0
- infrahub/prefect_server/models.py +46 -0
- infrahub/proposed_change/models.py +15 -1
- infrahub/proposed_change/tasks.py +173 -35
- infrahub/pytest_plugin.py +4 -4
- infrahub/server.py +12 -11
- infrahub/services/__init__.py +147 -62
- infrahub/services/adapters/cache/__init__.py +7 -5
- infrahub/services/adapters/cache/nats.py +40 -22
- infrahub/services/adapters/cache/redis.py +0 -4
- infrahub/services/adapters/event/__init__.py +10 -18
- infrahub/services/adapters/http/__init__.py +0 -5
- infrahub/services/adapters/http/httpx.py +22 -15
- infrahub/services/adapters/message_bus/__init__.py +23 -6
- infrahub/services/adapters/message_bus/local.py +8 -6
- infrahub/services/adapters/message_bus/nats.py +12 -6
- infrahub/services/adapters/message_bus/rabbitmq.py +22 -9
- infrahub/services/adapters/workflow/__init__.py +11 -8
- infrahub/services/adapters/workflow/local.py +28 -7
- infrahub/services/adapters/workflow/worker.py +23 -7
- infrahub/services/component.py +38 -35
- infrahub/services/scheduler.py +32 -29
- infrahub/storage.py +2 -4
- infrahub/task_manager/constants.py +1 -1
- infrahub/task_manager/event.py +182 -0
- infrahub/task_manager/models.py +125 -1
- infrahub/task_manager/task.py +1 -1
- infrahub/tasks/artifact.py +14 -16
- infrahub/tasks/registry.py +1 -1
- infrahub/tasks/telemetry.py +13 -14
- infrahub/transformations/tasks.py +3 -5
- infrahub/trigger/__init__.py +0 -0
- infrahub/trigger/catalogue.py +15 -0
- infrahub/trigger/constants.py +9 -0
- infrahub/trigger/models.py +69 -0
- infrahub/trigger/tasks.py +85 -0
- infrahub/types.py +1 -1
- infrahub/utils.py +1 -1
- infrahub/webhook/constants.py +0 -2
- infrahub/webhook/models.py +8 -2
- infrahub/webhook/tasks.py +20 -73
- infrahub/webhook/triggers.py +20 -0
- infrahub/workers/infrahub_async.py +36 -25
- infrahub/workers/utils.py +63 -0
- infrahub/workflows/catalogue.py +13 -37
- infrahub/workflows/initialization.py +6 -8
- infrahub/workflows/models.py +3 -5
- infrahub/workflows/utils.py +1 -1
- infrahub_sdk/ctl/check.py +3 -3
- infrahub_sdk/ctl/cli_commands.py +11 -10
- infrahub_sdk/ctl/exceptions.py +0 -6
- infrahub_sdk/ctl/exporter.py +1 -1
- infrahub_sdk/ctl/generator.py +5 -5
- infrahub_sdk/ctl/importer.py +3 -2
- infrahub_sdk/ctl/menu.py +1 -1
- infrahub_sdk/ctl/object.py +1 -1
- infrahub_sdk/ctl/repository.py +23 -15
- infrahub_sdk/ctl/schema.py +2 -2
- infrahub_sdk/ctl/utils.py +4 -3
- infrahub_sdk/ctl/validate.py +2 -1
- infrahub_sdk/exceptions.py +6 -0
- infrahub_sdk/generator.py +3 -0
- infrahub_sdk/node.py +2 -2
- infrahub_sdk/schema/__init__.py +14 -2
- infrahub_sdk/schema/main.py +7 -0
- infrahub_sdk/utils.py +11 -1
- infrahub_sdk/yaml.py +2 -3
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/METADATA +46 -12
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/RECORD +338 -321
- infrahub_testcontainers/container.py +14 -6
- infrahub_testcontainers/docker-compose.test.yml +24 -5
- infrahub_testcontainers/haproxy.cfg +43 -0
- infrahub_testcontainers/helpers.py +85 -1
- infrahub/core/branch/constants.py +0 -2
- infrahub/graphql/query.py +0 -52
- infrahub/message_bus/messages/request_artifactdefinition_check.py +0 -17
- infrahub/message_bus/operations/requests/artifact_definition.py +0 -148
- infrahub/schema/constants.py +0 -1
- infrahub/schema/tasks.py +0 -76
- infrahub/services/adapters/database/__init__.py +0 -9
- infrahub_sdk/ctl/_file.py +0 -13
- /infrahub/{schema → artifacts}/__init__.py +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/entry_points.txt +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, Any
|
|
2
2
|
|
|
3
3
|
from graphql import GraphQLResolveInfo
|
|
4
|
+
from graphql.type.definition import GraphQLNonNull
|
|
4
5
|
from infrahub_sdk.utils import deep_merge_dict, extract_fields
|
|
5
6
|
|
|
6
7
|
from infrahub.core.branch.models import Branch
|
|
@@ -31,9 +32,14 @@ class SingleRelationshipResolver:
|
|
|
31
32
|
"""
|
|
32
33
|
# Extract the InfraHub schema by inspecting the GQL Schema
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
# :
|
|
36
|
+
node_schema: NodeSchema = (
|
|
37
|
+
info.parent_type.of_type.graphene_type._meta.schema
|
|
38
|
+
if isinstance(info.parent_type, GraphQLNonNull)
|
|
39
|
+
else info.parent_type.graphene_type._meta.schema # type: ignore[attr-defined]
|
|
40
|
+
)
|
|
35
41
|
|
|
36
|
-
|
|
42
|
+
graphql_context: GraphqlContext = info.context
|
|
37
43
|
|
|
38
44
|
# Extract the name of the fields in the GQL query
|
|
39
45
|
fields = await extract_fields(info.field_nodes[0].selection_set)
|
|
@@ -53,10 +59,10 @@ class SingleRelationshipResolver:
|
|
|
53
59
|
|
|
54
60
|
if requires_relationship_metadata:
|
|
55
61
|
node_graph = await self._get_entities_simple(
|
|
56
|
-
db=
|
|
57
|
-
branch=
|
|
58
|
-
at=
|
|
59
|
-
related_node_ids=
|
|
62
|
+
db=graphql_context.db,
|
|
63
|
+
branch=graphql_context.branch,
|
|
64
|
+
at=graphql_context.at,
|
|
65
|
+
related_node_ids=graphql_context.related_node_ids,
|
|
60
66
|
field_name=info.field_name,
|
|
61
67
|
parent_id=parent["id"],
|
|
62
68
|
source_kind=node_schema.kind,
|
|
@@ -66,10 +72,10 @@ class SingleRelationshipResolver:
|
|
|
66
72
|
)
|
|
67
73
|
else:
|
|
68
74
|
node_graph = await self._get_entities_with_data_loader(
|
|
69
|
-
db=
|
|
70
|
-
branch=
|
|
71
|
-
at=
|
|
72
|
-
related_node_ids=
|
|
75
|
+
db=graphql_context.db,
|
|
76
|
+
branch=graphql_context.branch,
|
|
77
|
+
at=graphql_context.at,
|
|
78
|
+
related_node_ids=graphql_context.related_node_ids,
|
|
73
79
|
rel_schema=node_rel,
|
|
74
80
|
parent=parent,
|
|
75
81
|
node_fields=node_fields,
|
infrahub/graphql/schema.py
CHANGED
|
@@ -48,6 +48,7 @@ from .queries import (
|
|
|
48
48
|
Relationship,
|
|
49
49
|
)
|
|
50
50
|
from .queries.diff.tree import DiffTreeQuery, DiffTreeSummaryQuery
|
|
51
|
+
from .queries.event import Event
|
|
51
52
|
from .queries.task import Task, TaskBranchStatus
|
|
52
53
|
|
|
53
54
|
|
|
@@ -67,6 +68,7 @@ class InfrahubBaseQuery(ObjectType):
|
|
|
67
68
|
InfrahubSearchAnywhere = InfrahubSearchAnywhere
|
|
68
69
|
|
|
69
70
|
InfrahubTask = Task
|
|
71
|
+
InfrahubEvent = Event
|
|
70
72
|
InfrahubTaskBranchStatus = TaskBranchStatus
|
|
71
73
|
|
|
72
74
|
IPAddressGetNextAvailable = InfrahubIPAddressGetNextAvailable
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
# log = get_logger(name="infrahub.graphql")
|
|
21
21
|
|
|
22
|
-
# async def resolver_event(root: dict, info: GraphQLResolveInfo, topics: Optional[List] = None):
|
|
22
|
+
# async def resolver_event(root: dict, info: GraphQLResolveInfo, topics: Optional[List] = None):
|
|
23
23
|
# pass
|
|
24
24
|
# connection = await get_broker()
|
|
25
25
|
|
|
@@ -18,35 +18,35 @@ log = get_logger(name="infrahub.graphql")
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
async def resolver_graphql_query(
|
|
21
|
-
parent: dict, #
|
|
21
|
+
parent: dict, # noqa: ARG001
|
|
22
22
|
info: GraphQLResolveInfo,
|
|
23
23
|
name: str,
|
|
24
24
|
graphql_schema: Schema,
|
|
25
25
|
params: dict[str, Any] | None = None,
|
|
26
26
|
interval: int = 10,
|
|
27
27
|
) -> AsyncGenerator[dict[str, Any], None]:
|
|
28
|
-
|
|
28
|
+
graphql_context: GraphqlContext = info.context
|
|
29
29
|
at = Timestamp()
|
|
30
30
|
|
|
31
|
-
async with
|
|
31
|
+
async with graphql_context.db.start_session() as db:
|
|
32
32
|
# Find the GraphQLQuery and the GraphQL Schema
|
|
33
33
|
graphql_query = await NodeManager.get_one_by_default_filter(
|
|
34
|
-
db=db, id=name, kind=CoreGraphQLQuery, branch=
|
|
34
|
+
db=db, id=name, kind=CoreGraphQLQuery, branch=graphql_context.branch, at=at
|
|
35
35
|
)
|
|
36
36
|
if not graphql_query:
|
|
37
37
|
raise ValueError(f"Unable to find the {InfrahubKind.GRAPHQLQUERY} {name}")
|
|
38
38
|
|
|
39
39
|
while True:
|
|
40
|
-
async with
|
|
40
|
+
async with graphql_context.db.start_session() as db:
|
|
41
41
|
result = await graphql(
|
|
42
42
|
schema=graphql_schema,
|
|
43
43
|
source=graphql_query.query.value,
|
|
44
|
-
context_value=
|
|
44
|
+
context_value=graphql_context.__class__(
|
|
45
45
|
db=db,
|
|
46
|
-
branch=
|
|
46
|
+
branch=graphql_context.branch,
|
|
47
47
|
at=Timestamp(),
|
|
48
48
|
related_node_ids=set(),
|
|
49
|
-
types=
|
|
49
|
+
types=graphql_context.types,
|
|
50
50
|
single_relationship_resolver=SingleRelationshipResolver(),
|
|
51
51
|
),
|
|
52
52
|
root_value=None,
|
infrahub/graphql/types/branch.py
CHANGED
|
@@ -34,10 +34,10 @@ class BranchType(InfrahubObjectType):
|
|
|
34
34
|
async def get_list(
|
|
35
35
|
cls,
|
|
36
36
|
fields: dict,
|
|
37
|
-
|
|
37
|
+
graphql_context: GraphqlContext,
|
|
38
38
|
**kwargs: Any,
|
|
39
39
|
) -> list[dict[str, Any]]:
|
|
40
|
-
async with
|
|
40
|
+
async with graphql_context.db.start_session() as db:
|
|
41
41
|
objs = await Branch.get_list(db=db, **kwargs)
|
|
42
42
|
|
|
43
43
|
if not objs:
|
infrahub/graphql/types/common.py
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from graphene import InputObjectType, String
|
|
3
|
+
from graphene import InputObjectType, ObjectType, String
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class IdentifierInput(InputObjectType):
|
|
7
7
|
id = String(required=True, description="The ID of the requested object")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RelatedNode(ObjectType):
|
|
11
|
+
id = String(required=True, description="The ID of the requested object")
|
|
12
|
+
kind = String(required=True, description="The ID of the requested object")
|
infrahub/graphql/types/enums.py
CHANGED
|
@@ -5,6 +5,8 @@ from infrahub.permissions import constants as permission_constants
|
|
|
5
5
|
|
|
6
6
|
CheckType = Enum.from_enum(constants.CheckType)
|
|
7
7
|
|
|
8
|
+
DiffAction = Enum.from_enum(constants.DiffAction)
|
|
9
|
+
|
|
8
10
|
Severity = Enum.from_enum(constants.Severity)
|
|
9
11
|
|
|
10
12
|
BranchRelativePermissionDecision = Enum.from_enum(permission_constants.BranchRelativePermissionDecision)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from graphene import Boolean, DateTime, Field, Int, Interface, List, NonNull, ObjectType, String
|
|
6
|
+
from graphene.types.generic import GenericScalar
|
|
7
|
+
|
|
8
|
+
from .common import RelatedNode
|
|
9
|
+
from .enums import DiffAction
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from graphql import GraphQLResolveInfo
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class InfrahubMutatedAttribute(ObjectType):
|
|
16
|
+
name = String(required=True)
|
|
17
|
+
action = DiffAction(required=True)
|
|
18
|
+
value = String(required=False)
|
|
19
|
+
kind = String(required=True)
|
|
20
|
+
value_previous = String(required=False)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class EventNodeInterface(Interface):
|
|
24
|
+
id = String(required=True)
|
|
25
|
+
event = String(required=True)
|
|
26
|
+
branch = String(required=False)
|
|
27
|
+
account_id = String(required=False)
|
|
28
|
+
occurred_at = DateTime(required=True)
|
|
29
|
+
level = Int(required=True)
|
|
30
|
+
primary_node = Field(RelatedNode, required=False)
|
|
31
|
+
related_nodes = List(NonNull(RelatedNode), required=True)
|
|
32
|
+
has_children = Boolean(required=True)
|
|
33
|
+
parent_id = String(required=False)
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def resolve_type(
|
|
37
|
+
cls,
|
|
38
|
+
instance: dict[str, Any],
|
|
39
|
+
info: GraphQLResolveInfo, # noqa: ARG003
|
|
40
|
+
) -> type[ObjectType]:
|
|
41
|
+
if "event" in instance:
|
|
42
|
+
return EVENT_TYPES.get(instance["event"], StandardEvent)
|
|
43
|
+
return StandardEvent
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class EventNodes(ObjectType):
|
|
47
|
+
node = Field(EventNodeInterface)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# ---------------------------------------
|
|
51
|
+
# Branch events
|
|
52
|
+
# ---------------------------------------
|
|
53
|
+
class BranchCreatedEvent(ObjectType):
|
|
54
|
+
class Meta:
|
|
55
|
+
interfaces = (EventNodeInterface,)
|
|
56
|
+
|
|
57
|
+
payload = Field(GenericScalar, required=True)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class BranchRebasedEvent(ObjectType):
|
|
61
|
+
class Meta:
|
|
62
|
+
interfaces = (EventNodeInterface,)
|
|
63
|
+
|
|
64
|
+
payload = Field(GenericScalar, required=True)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class BranchDeletedEvent(ObjectType):
|
|
68
|
+
class Meta:
|
|
69
|
+
interfaces = (EventNodeInterface,)
|
|
70
|
+
|
|
71
|
+
payload = Field(GenericScalar, required=True)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# ---------------------------------------
|
|
75
|
+
# Node/Object events
|
|
76
|
+
# ---------------------------------------
|
|
77
|
+
class NodeMutatedEvent(ObjectType):
|
|
78
|
+
class Meta:
|
|
79
|
+
interfaces = (EventNodeInterface,)
|
|
80
|
+
|
|
81
|
+
payload = Field(GenericScalar, required=True)
|
|
82
|
+
attributes = Field(List(of_type=NonNull(InfrahubMutatedAttribute), required=True), required=True)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class StandardEvent(ObjectType):
|
|
86
|
+
class Meta:
|
|
87
|
+
interfaces = (EventNodeInterface,)
|
|
88
|
+
|
|
89
|
+
payload = Field(GenericScalar, required=True)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
EVENT_TYPES: dict[str, type[ObjectType]] = {
|
|
93
|
+
"infrahub.node.created": NodeMutatedEvent,
|
|
94
|
+
"infrahub.node.updated": NodeMutatedEvent,
|
|
95
|
+
"infrahub.node.deleted": NodeMutatedEvent,
|
|
96
|
+
"infrahub.branch.created": BranchCreatedEvent,
|
|
97
|
+
"infrahub.branch.rebased": BranchRebasedEvent,
|
|
98
|
+
"infrahub.branch.deleted": BranchDeletedEvent,
|
|
99
|
+
"undefined": StandardEvent,
|
|
100
|
+
}
|
|
@@ -21,8 +21,8 @@ class InfrahubInterfaceOptions(InterfaceOptions):
|
|
|
21
21
|
class InfrahubInterface(Interface):
|
|
22
22
|
@classmethod
|
|
23
23
|
def resolve_type(cls, instance: dict[str, Any], info: GraphQLResolveInfo) -> InfrahubObject:
|
|
24
|
-
|
|
24
|
+
graphql_context: GraphqlContext = info.context
|
|
25
25
|
if KIND_GRAPHQL_FIELD_NAME in instance:
|
|
26
|
-
return
|
|
26
|
+
return graphql_context.types[instance[KIND_GRAPHQL_FIELD_NAME]]
|
|
27
27
|
|
|
28
28
|
raise ValueError("Unable to identify the type of the instance.")
|
infrahub/graphql/types/node.py
CHANGED
|
@@ -5,7 +5,7 @@ from typing import Any, Optional
|
|
|
5
5
|
from graphene import ObjectType
|
|
6
6
|
from graphene.types.objecttype import ObjectTypeOptions
|
|
7
7
|
|
|
8
|
-
from infrahub.core.schema import GenericSchema, MainSchemaTypes, NodeSchema, ProfileSchema
|
|
8
|
+
from infrahub.core.schema import GenericSchema, MainSchemaTypes, NodeSchema, ProfileSchema, TemplateSchema
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class InfrahubObjectOptions(ObjectTypeOptions):
|
|
@@ -14,14 +14,14 @@ class InfrahubObjectOptions(ObjectTypeOptions):
|
|
|
14
14
|
|
|
15
15
|
class InfrahubObject(ObjectType):
|
|
16
16
|
@classmethod
|
|
17
|
-
def __init_subclass_with_meta__(
|
|
17
|
+
def __init_subclass_with_meta__(
|
|
18
18
|
cls,
|
|
19
19
|
schema: Optional[MainSchemaTypes] = None,
|
|
20
20
|
interfaces: tuple = (),
|
|
21
21
|
_meta: InfrahubObjectOptions | None = None,
|
|
22
22
|
**options: Any,
|
|
23
23
|
) -> None:
|
|
24
|
-
if not isinstance(schema,
|
|
24
|
+
if not isinstance(schema, NodeSchema | GenericSchema | ProfileSchema | TemplateSchema):
|
|
25
25
|
raise ValueError(f"You need to pass a valid NodeSchema in '{cls.__name__}.Meta', received '{schema}'")
|
|
26
26
|
|
|
27
27
|
if not _meta:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from graphene import Field, Int, List, ObjectType, String
|
|
3
|
+
from graphene import Field, Int, List, NonNull, ObjectType, String
|
|
4
4
|
|
|
5
5
|
from infrahub.graphql.types.enums import BranchRelativePermissionDecision
|
|
6
6
|
|
|
@@ -39,4 +39,4 @@ class PaginatedObjectPermission(ObjectType):
|
|
|
39
39
|
required=True,
|
|
40
40
|
description="The number of permissions applicable, will be 1 for normal nodes or possibly more for generics",
|
|
41
41
|
)
|
|
42
|
-
edges = Field(List(of_type=ObjectPermissionNode, required=True), required=True)
|
|
42
|
+
edges = Field(List(of_type=NonNull(ObjectPermissionNode), required=True), required=True)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from graphene import Field, List, ObjectType, String
|
|
3
|
+
from graphene import Field, List, NonNull, ObjectType, String
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class RelationshipPeer(ObjectType):
|
|
@@ -11,8 +11,8 @@ class RelationshipPeer(ObjectType):
|
|
|
11
11
|
class Relationship(ObjectType):
|
|
12
12
|
id = String(required=False)
|
|
13
13
|
identifier = String(required=False)
|
|
14
|
-
peers = List(RelationshipPeer)
|
|
14
|
+
peers = List(NonNull(RelationshipPeer))
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class RelationshipNode(ObjectType):
|
|
18
|
-
node = Field(Relationship)
|
|
18
|
+
node = Field(Relationship, required=True)
|
|
@@ -17,9 +17,7 @@ class InfrahubObjectTypeOptions(ObjectTypeOptions):
|
|
|
17
17
|
|
|
18
18
|
class InfrahubObjectType(ObjectType):
|
|
19
19
|
@classmethod
|
|
20
|
-
def __init_subclass_with_meta__(
|
|
21
|
-
cls, model=None, interfaces=(), _meta=None, **options
|
|
22
|
-
) -> None:
|
|
20
|
+
def __init_subclass_with_meta__(cls, model=None, interfaces=(), _meta=None, **options) -> None:
|
|
23
21
|
if not _meta:
|
|
24
22
|
_meta = InfrahubObjectTypeOptions(cls)
|
|
25
23
|
|
|
@@ -28,24 +26,24 @@ class InfrahubObjectType(ObjectType):
|
|
|
28
26
|
super().__init_subclass_with_meta__(_meta=_meta, interfaces=interfaces, **options)
|
|
29
27
|
|
|
30
28
|
@classmethod
|
|
31
|
-
async def get_list(cls, fields: dict[str, Any],
|
|
32
|
-
async with
|
|
29
|
+
async def get_list(cls, fields: dict[str, Any], graphql_context: GraphqlContext, **kwargs) -> list[dict[str, Any]]:
|
|
30
|
+
async with graphql_context.db.session(database=config.SETTINGS.database.database_name) as db:
|
|
33
31
|
filters = {key: value for key, value in kwargs.items() if "__" in key and value}
|
|
34
32
|
|
|
35
33
|
if filters:
|
|
36
34
|
objs = await cls._meta.model.get_list(
|
|
37
35
|
filters=filters,
|
|
38
|
-
at=
|
|
39
|
-
branch=
|
|
40
|
-
account=
|
|
36
|
+
at=graphql_context.at,
|
|
37
|
+
branch=graphql_context.branch,
|
|
38
|
+
account=graphql_context.account_session,
|
|
41
39
|
include_source=True,
|
|
42
40
|
db=db,
|
|
43
41
|
)
|
|
44
42
|
else:
|
|
45
43
|
objs = await cls._meta.model.get_list(
|
|
46
|
-
at=
|
|
47
|
-
branch=
|
|
48
|
-
account=
|
|
44
|
+
at=graphql_context.at,
|
|
45
|
+
branch=graphql_context.branch,
|
|
46
|
+
account=graphql_context.account_session,
|
|
49
47
|
include_source=True,
|
|
50
48
|
db=db,
|
|
51
49
|
)
|
infrahub/graphql/utils.py
CHANGED
|
@@ -3,24 +3,16 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import TYPE_CHECKING, Union
|
|
4
4
|
|
|
5
5
|
from graphene.types.definitions import GrapheneInterfaceType, GrapheneObjectType
|
|
6
|
-
from graphql import (
|
|
7
|
-
ExecutionContext,
|
|
8
|
-
FieldNode,
|
|
9
|
-
FragmentSpreadNode,
|
|
6
|
+
from graphql import (
|
|
10
7
|
GraphQLList,
|
|
11
|
-
|
|
12
|
-
GraphQLResolveInfo,
|
|
8
|
+
GraphQLNonNull,
|
|
13
9
|
GraphQLSchema,
|
|
14
10
|
GraphQLUnionType,
|
|
15
|
-
InlineFragmentNode,
|
|
16
|
-
SelectionSetNode,
|
|
17
11
|
)
|
|
18
12
|
|
|
19
13
|
from infrahub.exceptions import GraphQLQueryError
|
|
20
14
|
|
|
21
15
|
if TYPE_CHECKING:
|
|
22
|
-
import abc
|
|
23
|
-
|
|
24
16
|
from graphql.execution import ExecutionResult
|
|
25
17
|
|
|
26
18
|
|
|
@@ -42,171 +34,6 @@ def extract_data(query_name: str, result: ExecutionResult) -> dict:
|
|
|
42
34
|
return result.data or {}
|
|
43
35
|
|
|
44
36
|
|
|
45
|
-
# --------------------------------------------------------------
|
|
46
|
-
# The functions below :
|
|
47
|
-
# - selected_field_names_fast
|
|
48
|
-
# - selected_field_names_naive
|
|
49
|
-
# - selected_field_names
|
|
50
|
-
# - selected_field_names_from_context
|
|
51
|
-
# Are not currently used and they have been copied from internet as a reference
|
|
52
|
-
# >> https://github.com/graphql-python/graphene/issues/57#issuecomment-774227086
|
|
53
|
-
#
|
|
54
|
-
# --------------------------------------------------------------
|
|
55
|
-
def selected_field_names_fast(
|
|
56
|
-
selection_set: SelectionSetNode, context: GraphQLResolveInfo, runtime_type: Union[str, GraphQLObjectType] = None
|
|
57
|
-
) -> abc.Iterator[str]:
|
|
58
|
-
"""Use the fastest available function to provide the list of selected field names
|
|
59
|
-
|
|
60
|
-
Note that this function may give false positives because in the absence of fragments it ignores directives.
|
|
61
|
-
"""
|
|
62
|
-
# Any fragments?
|
|
63
|
-
no_fragments = all(isinstance(node, FieldNode) for node in selection_set.selections)
|
|
64
|
-
|
|
65
|
-
# Choose the function to execute
|
|
66
|
-
if no_fragments:
|
|
67
|
-
return selected_field_names_naive(selection_set)
|
|
68
|
-
|
|
69
|
-
return selected_field_names(selection_set, context, runtime_type)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def selected_field_names_naive(selection_set: SelectionSetNode) -> list:
|
|
73
|
-
"""Get the list of field names that are selected at the current level. Does not include nested names.
|
|
74
|
-
|
|
75
|
-
Limitations:
|
|
76
|
-
* Does not resolve fragments; throws RuntimeError
|
|
77
|
-
* Does not take directives into account. A field might be disabled, and this function wouldn't know
|
|
78
|
-
|
|
79
|
-
As a result:
|
|
80
|
-
* It will give a RuntimeError if a fragment is provided
|
|
81
|
-
* It may give false positives in case directives are used
|
|
82
|
-
* It is 20x faster than the alternative
|
|
83
|
-
|
|
84
|
-
Benefits:
|
|
85
|
-
* Fast!
|
|
86
|
-
|
|
87
|
-
Args:
|
|
88
|
-
selection_set: the selected fields
|
|
89
|
-
|
|
90
|
-
Code copied from https://github.com/graphql-python/graphene/issues/57#issuecomment-774227086
|
|
91
|
-
This link also includes a more powerful and complexe alternative.
|
|
92
|
-
"""
|
|
93
|
-
assert isinstance(selection_set, SelectionSetNode)
|
|
94
|
-
|
|
95
|
-
field_names = []
|
|
96
|
-
|
|
97
|
-
for node in selection_set.selections:
|
|
98
|
-
# Field
|
|
99
|
-
if isinstance(node, FieldNode):
|
|
100
|
-
field_names.append(node.name.value)
|
|
101
|
-
# Fragment spread (`... fragmentName`)
|
|
102
|
-
elif isinstance(node, (FragmentSpreadNode, InlineFragmentNode)):
|
|
103
|
-
raise NotImplementedError("Fragments are not supported by this simplistic function")
|
|
104
|
-
# Something new
|
|
105
|
-
else:
|
|
106
|
-
raise NotImplementedError(str(type(node)))
|
|
107
|
-
|
|
108
|
-
return field_names
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
def selected_field_names(
|
|
112
|
-
selection_set: SelectionSetNode, info: GraphQLResolveInfo, runtime_type: Union[str, GraphQLObjectType] = None
|
|
113
|
-
) -> abc.Iterator[str]:
|
|
114
|
-
"""Get the list of field names that are selected at the current level. Does not include nested names.
|
|
115
|
-
|
|
116
|
-
This function re-evaluates the AST, but gives a complete list of included fields.
|
|
117
|
-
It is 25x slower than `selected_field_names_naive()`, but still, it completes in 7ns or so. Not bad.
|
|
118
|
-
|
|
119
|
-
Args:
|
|
120
|
-
selection_set: the selected fields
|
|
121
|
-
info: GraphQL resolve info
|
|
122
|
-
runtime_type: The type of the object you resolve to. Either its string name, or its ObjectType.
|
|
123
|
-
If none is provided, this function will fail with a RuntimeError() when resolving fragments
|
|
124
|
-
"""
|
|
125
|
-
# pylint: disable=no-value-for-parameter
|
|
126
|
-
|
|
127
|
-
# Create a temporary execution context. This operation is quite cheap, actually.
|
|
128
|
-
execution_context = ExecutionContext(
|
|
129
|
-
schema=info.schema,
|
|
130
|
-
fragments=info.fragments,
|
|
131
|
-
root_value=info.root_value,
|
|
132
|
-
operation=info.operation,
|
|
133
|
-
variable_values=info.variable_values,
|
|
134
|
-
# The only purpose of this context is to be able to run the collect_fields() method.
|
|
135
|
-
# Therefore, many parameters are actually irrelevant
|
|
136
|
-
context_value=None,
|
|
137
|
-
field_resolver=None,
|
|
138
|
-
type_resolver=None,
|
|
139
|
-
errors=[],
|
|
140
|
-
middleware_manager=None,
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
# Use it
|
|
144
|
-
return selected_field_names_from_context(selection_set, execution_context, runtime_type)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def selected_field_names_from_context(
|
|
148
|
-
selection_set: SelectionSetNode, context: ExecutionContext, runtime_type: Union[str, GraphQLObjectType] = None
|
|
149
|
-
) -> abc.Iterator[str]:
|
|
150
|
-
"""Get the list of field names that are selected at the current level.
|
|
151
|
-
|
|
152
|
-
This function is useless because `graphql.ExecutionContext` is not available at all inside resolvers.
|
|
153
|
-
Therefore, `selected_field_names()` wraps it and provides one.
|
|
154
|
-
"""
|
|
155
|
-
assert isinstance(selection_set, SelectionSetNode)
|
|
156
|
-
|
|
157
|
-
# Resolve `runtime_type`
|
|
158
|
-
if isinstance(runtime_type, str):
|
|
159
|
-
runtime_type = context.schema.type_map[runtime_type] # raises: KeyError
|
|
160
|
-
|
|
161
|
-
# Resolve all fields
|
|
162
|
-
fields_map = context.collect_fields(
|
|
163
|
-
# Use the provided Object type, or use a dummy object that fails all tests
|
|
164
|
-
runtime_type=runtime_type or None,
|
|
165
|
-
# runtime_type=runtime_type or graphql.GraphQLObjectType('<temp>', []),
|
|
166
|
-
selection_set=selection_set,
|
|
167
|
-
fields={}, # out
|
|
168
|
-
visited_fragment_names=(visited_fragment_names := set()), # out
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
# Test fragment resolution
|
|
172
|
-
if visited_fragment_names and not runtime_type:
|
|
173
|
-
raise RuntimeError(
|
|
174
|
-
"The query contains fragments which cannot be resolved "
|
|
175
|
-
"because `runtime_type` is not provided by the lazy developer"
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
# Results!
|
|
179
|
-
return (field.name.value for fields_list in fields_map.values() for field in fields_list)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
def print_query(info: GraphQLResolveInfo) -> None:
|
|
183
|
-
"""Traverse the query"""
|
|
184
|
-
initial_selection_set = info.field_nodes[0].selection_set
|
|
185
|
-
print_selection_set(initial_selection_set, 1)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
def print_selection_set(selection_set: SelectionSetNode, level: int = 1) -> int:
|
|
189
|
-
# max_depth = level
|
|
190
|
-
tab = " "
|
|
191
|
-
for field in getattr(selection_set, "selections", []):
|
|
192
|
-
# print(f"in print_selection_set loop {field}")
|
|
193
|
-
# The field we are at is already a lever deeper, even if it doesn't have its own selection set.
|
|
194
|
-
# max_depth = max(max_depth, level + 1)
|
|
195
|
-
print(f"{level * tab}{field.name.value}")
|
|
196
|
-
if selection_set := getattr(field, "selection_set", None):
|
|
197
|
-
# max_depth = max(max_depth, self._get_query_depth(selection_set, level + 1))
|
|
198
|
-
print_selection_set(selection_set, level + 1)
|
|
199
|
-
|
|
200
|
-
# """
|
|
201
|
-
# MATCH (d:Device)
|
|
202
|
-
# WHERE (d)-[]-(:Attribute {name: "name"})-[]-(:AttributeValue {value: "spine1"})
|
|
203
|
-
# MAT36CH (d)-[:IS_RELATED]-(r1:Relationship{type: "device_interface"})-[:IS_RELATED]-(n1)
|
|
204
|
-
# WHERE (n1)-[]-(:Attribute {name: "enabled"})-[]-(:AttributeValue {value: false})
|
|
205
|
-
# OPTIONAL MATCH (d)-[:IS_RELATED]-(r1)-[:IS_RELATED]-(n1)-[:IS_RELATED]-(r2:Relationship {type: "interface_ip"})-[:IS_RELATED]-(n2)
|
|
206
|
-
# RETURN d,n1,r1,n2,r2
|
|
207
|
-
# """
|
|
208
|
-
|
|
209
|
-
|
|
210
37
|
def find_types_implementing_interface(
|
|
211
38
|
interface: GrapheneInterfaceType, root_schema: GraphQLSchema
|
|
212
39
|
) -> list[GrapheneObjectType]:
|
|
@@ -234,12 +61,19 @@ async def extract_schema_models(
|
|
|
234
61
|
if field_name not in schema.fields:
|
|
235
62
|
continue
|
|
236
63
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
object_type =
|
|
64
|
+
gql_type = schema.fields[field_name].type
|
|
65
|
+
if isinstance(schema.fields[field_name].type, GraphQLNonNull):
|
|
66
|
+
gql_type = schema.fields[field_name].type.of_type
|
|
67
|
+
|
|
68
|
+
if isinstance(gql_type, GrapheneObjectType):
|
|
69
|
+
object_type = gql_type
|
|
70
|
+
elif isinstance(gql_type, GraphQLList):
|
|
71
|
+
if isinstance(gql_type.of_type, GraphQLNonNull):
|
|
72
|
+
object_type = gql_type.of_type.of_type
|
|
73
|
+
else:
|
|
74
|
+
object_type = gql_type.of_type
|
|
75
|
+
elif isinstance(gql_type, GrapheneInterfaceType):
|
|
76
|
+
object_type = gql_type
|
|
243
77
|
sub_types = find_types_implementing_interface(interface=object_type, root_schema=root_schema)
|
|
244
78
|
for sub_type in sub_types:
|
|
245
79
|
response.add(sub_type.name)
|
|
@@ -247,6 +81,15 @@ async def extract_schema_models(
|
|
|
247
81
|
else:
|
|
248
82
|
continue
|
|
249
83
|
|
|
84
|
+
# Ensure that Attribute types are not reported by this function
|
|
85
|
+
if isinstance(object_type, GrapheneObjectType) and object_type.interfaces:
|
|
86
|
+
inherit_from = [intf.name for intf in object_type.interfaces]
|
|
87
|
+
if "AttributeInterface" in inherit_from:
|
|
88
|
+
continue
|
|
89
|
+
|
|
90
|
+
if isinstance(object_type, GraphQLNonNull):
|
|
91
|
+
raise ValueError("object_type shouldn't be a of type GraphQLNonNull")
|
|
92
|
+
|
|
250
93
|
response.add(object_type.name)
|
|
251
94
|
|
|
252
95
|
if isinstance(value, dict):
|
|
@@ -255,6 +98,9 @@ async def extract_schema_models(
|
|
|
255
98
|
if isinstance(schema.fields[value].type, GrapheneObjectType):
|
|
256
99
|
response.add(schema.fields[value].type.name)
|
|
257
100
|
elif isinstance(schema.fields[value].type, GraphQLList):
|
|
258
|
-
|
|
101
|
+
if isinstance(schema.fields[value].type.of_type, GraphQLNonNull):
|
|
102
|
+
response.add(schema.fields[value].type.of_type.of_type.name)
|
|
103
|
+
else:
|
|
104
|
+
response.add(schema.fields[value].type.of_type.name)
|
|
259
105
|
|
|
260
106
|
return response
|
infrahub/groups/tasks.py
CHANGED
|
@@ -4,12 +4,12 @@ from prefect import flow
|
|
|
4
4
|
|
|
5
5
|
from infrahub.core.constants import InfrahubKind
|
|
6
6
|
from infrahub.groups.models import RequestGraphQLQueryGroupUpdate
|
|
7
|
-
from infrahub.services import
|
|
7
|
+
from infrahub.services import InfrahubServices
|
|
8
8
|
from infrahub.workflows.utils import add_tags
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
@flow(name="graphql-query-group-update", flow_run_name="Update GraphQLQuery Group '{model.query_name}'")
|
|
12
|
-
async def update_graphql_query_group(model: RequestGraphQLQueryGroupUpdate) -> None:
|
|
12
|
+
async def update_graphql_query_group(model: RequestGraphQLQueryGroupUpdate, service: InfrahubServices) -> None:
|
|
13
13
|
"""Create or Update a GraphQLQueryGroup."""
|
|
14
14
|
|
|
15
15
|
# If there is only one subscriber, associate the task to it
|
|
@@ -19,7 +19,6 @@ async def update_graphql_query_group(model: RequestGraphQLQueryGroupUpdate) -> N
|
|
|
19
19
|
related_nodes.append(model.subscribers[0])
|
|
20
20
|
|
|
21
21
|
await add_tags(branches=[model.branch], nodes=related_nodes)
|
|
22
|
-
service = services.service
|
|
23
22
|
|
|
24
23
|
params_hash = dict_hash(model.params)
|
|
25
24
|
group_name = f"{model.query_name}__{params_hash}"
|
infrahub/lock.py
CHANGED
|
@@ -253,7 +253,7 @@ class InfrahubLockRegistry:
|
|
|
253
253
|
|
|
254
254
|
|
|
255
255
|
def initialize_lock(local_only: bool = False, service: Optional[InfrahubServices] = None) -> None:
|
|
256
|
-
global registry
|
|
256
|
+
global registry
|
|
257
257
|
registry = InfrahubLockRegistry(local_only=local_only, service=service)
|
|
258
258
|
|
|
259
259
|
|