infrahub-server 1.4.13__py3-none-any.whl → 1.5.0__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/actions/tasks.py +208 -16
- infrahub/api/artifact.py +3 -0
- infrahub/api/diff/diff.py +1 -1
- infrahub/api/internal.py +2 -0
- infrahub/api/query.py +2 -0
- infrahub/api/schema.py +27 -3
- infrahub/auth.py +5 -5
- infrahub/cli/__init__.py +2 -0
- infrahub/cli/db.py +160 -157
- infrahub/cli/dev.py +118 -0
- infrahub/cli/upgrade.py +56 -9
- infrahub/computed_attribute/tasks.py +19 -7
- infrahub/config.py +7 -2
- infrahub/core/attribute.py +35 -24
- infrahub/core/branch/enums.py +1 -1
- infrahub/core/branch/models.py +9 -5
- infrahub/core/branch/needs_rebase_status.py +11 -0
- infrahub/core/branch/tasks.py +72 -10
- infrahub/core/changelog/models.py +2 -10
- infrahub/core/constants/__init__.py +4 -0
- infrahub/core/constants/infrahubkind.py +1 -0
- infrahub/core/convert_object_type/object_conversion.py +201 -0
- infrahub/core/convert_object_type/repository_conversion.py +89 -0
- infrahub/core/convert_object_type/schema_mapping.py +27 -3
- infrahub/core/diff/model/path.py +4 -0
- infrahub/core/diff/payload_builder.py +1 -1
- infrahub/core/diff/query/artifact.py +1 -0
- infrahub/core/diff/query/field_summary.py +1 -0
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/initialization.py +7 -4
- infrahub/core/manager.py +3 -81
- infrahub/core/migrations/__init__.py +3 -0
- infrahub/core/migrations/exceptions.py +4 -0
- infrahub/core/migrations/graph/__init__.py +11 -10
- infrahub/core/migrations/graph/load_schema_branch.py +21 -0
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +1 -1
- infrahub/core/migrations/graph/m037_index_attr_vals.py +11 -30
- infrahub/core/migrations/graph/m039_ipam_reconcile.py +9 -7
- infrahub/core/migrations/graph/m042_profile_attrs_in_db.py +147 -0
- infrahub/core/migrations/graph/m043_create_hfid_display_label_in_db.py +164 -0
- infrahub/core/migrations/graph/m044_backfill_hfid_display_label_in_db.py +864 -0
- infrahub/core/migrations/query/__init__.py +7 -8
- infrahub/core/migrations/query/attribute_add.py +8 -6
- infrahub/core/migrations/query/attribute_remove.py +134 -0
- infrahub/core/migrations/runner.py +54 -0
- infrahub/core/migrations/schema/attribute_kind_update.py +9 -3
- infrahub/core/migrations/schema/attribute_supports_profile.py +90 -0
- infrahub/core/migrations/schema/node_attribute_add.py +26 -5
- infrahub/core/migrations/schema/node_attribute_remove.py +13 -109
- infrahub/core/migrations/schema/node_kind_update.py +2 -1
- infrahub/core/migrations/schema/node_remove.py +2 -1
- infrahub/core/migrations/schema/placeholder_dummy.py +3 -2
- infrahub/core/migrations/shared.py +66 -19
- infrahub/core/models.py +2 -2
- infrahub/core/node/__init__.py +207 -54
- infrahub/core/node/create.py +53 -49
- infrahub/core/node/lock_utils.py +124 -0
- infrahub/core/node/node_property_attribute.py +230 -0
- infrahub/core/node/resource_manager/ip_address_pool.py +2 -1
- infrahub/core/node/resource_manager/ip_prefix_pool.py +2 -1
- infrahub/core/node/resource_manager/number_pool.py +2 -1
- infrahub/core/node/standard.py +1 -1
- infrahub/core/property.py +11 -0
- infrahub/core/protocols.py +8 -1
- infrahub/core/query/attribute.py +82 -15
- infrahub/core/query/ipam.py +16 -4
- infrahub/core/query/node.py +66 -188
- infrahub/core/query/relationship.py +44 -26
- infrahub/core/query/subquery.py +0 -8
- infrahub/core/relationship/model.py +69 -24
- infrahub/core/schema/__init__.py +56 -0
- infrahub/core/schema/attribute_schema.py +4 -2
- infrahub/core/schema/basenode_schema.py +42 -2
- infrahub/core/schema/definitions/core/__init__.py +2 -0
- infrahub/core/schema/definitions/core/check.py +1 -1
- infrahub/core/schema/definitions/core/generator.py +2 -0
- infrahub/core/schema/definitions/core/group.py +16 -2
- infrahub/core/schema/definitions/core/repository.py +7 -0
- infrahub/core/schema/definitions/core/transform.py +1 -1
- infrahub/core/schema/definitions/internal.py +12 -3
- infrahub/core/schema/generated/attribute_schema.py +2 -2
- infrahub/core/schema/generated/base_node_schema.py +6 -1
- infrahub/core/schema/manager.py +3 -0
- infrahub/core/schema/node_schema.py +1 -0
- infrahub/core/schema/relationship_schema.py +0 -1
- infrahub/core/schema/schema_branch.py +295 -10
- infrahub/core/schema/schema_branch_display.py +135 -0
- infrahub/core/schema/schema_branch_hfid.py +120 -0
- infrahub/core/validators/aggregated_checker.py +1 -1
- infrahub/database/graph.py +21 -0
- infrahub/display_labels/__init__.py +0 -0
- infrahub/display_labels/gather.py +48 -0
- infrahub/display_labels/models.py +240 -0
- infrahub/display_labels/tasks.py +192 -0
- infrahub/display_labels/triggers.py +22 -0
- infrahub/events/branch_action.py +27 -1
- infrahub/events/group_action.py +1 -1
- infrahub/events/node_action.py +1 -1
- infrahub/generators/constants.py +7 -0
- infrahub/generators/models.py +38 -12
- infrahub/generators/tasks.py +34 -16
- infrahub/git/base.py +38 -1
- infrahub/git/integrator.py +22 -14
- infrahub/graphql/api/dependencies.py +2 -4
- infrahub/graphql/api/endpoints.py +16 -6
- infrahub/graphql/app.py +2 -4
- infrahub/graphql/initialization.py +2 -3
- infrahub/graphql/manager.py +213 -137
- infrahub/graphql/middleware.py +12 -0
- infrahub/graphql/mutations/branch.py +16 -0
- infrahub/graphql/mutations/computed_attribute.py +110 -3
- infrahub/graphql/mutations/convert_object_type.py +44 -13
- infrahub/graphql/mutations/display_label.py +118 -0
- infrahub/graphql/mutations/generator.py +25 -7
- infrahub/graphql/mutations/hfid.py +125 -0
- infrahub/graphql/mutations/ipam.py +73 -41
- infrahub/graphql/mutations/main.py +61 -178
- infrahub/graphql/mutations/profile.py +195 -0
- infrahub/graphql/mutations/proposed_change.py +8 -1
- infrahub/graphql/mutations/relationship.py +2 -2
- infrahub/graphql/mutations/repository.py +22 -83
- infrahub/graphql/mutations/resource_manager.py +2 -2
- infrahub/graphql/mutations/webhook.py +1 -1
- infrahub/graphql/queries/resource_manager.py +1 -1
- infrahub/graphql/registry.py +173 -0
- infrahub/graphql/resolvers/resolver.py +2 -0
- infrahub/graphql/schema.py +8 -1
- infrahub/graphql/schema_sort.py +170 -0
- infrahub/graphql/types/branch.py +4 -1
- infrahub/graphql/types/enums.py +3 -0
- infrahub/groups/tasks.py +1 -1
- infrahub/hfid/__init__.py +0 -0
- infrahub/hfid/gather.py +48 -0
- infrahub/hfid/models.py +240 -0
- infrahub/hfid/tasks.py +191 -0
- infrahub/hfid/triggers.py +22 -0
- infrahub/lock.py +119 -42
- infrahub/locks/__init__.py +0 -0
- infrahub/locks/tasks.py +37 -0
- infrahub/patch/plan_writer.py +2 -2
- infrahub/permissions/constants.py +2 -0
- infrahub/profiles/__init__.py +0 -0
- infrahub/profiles/node_applier.py +101 -0
- infrahub/profiles/queries/__init__.py +0 -0
- infrahub/profiles/queries/get_profile_data.py +98 -0
- infrahub/profiles/tasks.py +63 -0
- infrahub/proposed_change/tasks.py +24 -5
- infrahub/repositories/__init__.py +0 -0
- infrahub/repositories/create_repository.py +113 -0
- infrahub/server.py +9 -1
- infrahub/services/__init__.py +8 -5
- infrahub/services/adapters/workflow/worker.py +5 -2
- infrahub/task_manager/event.py +5 -0
- infrahub/task_manager/models.py +7 -0
- infrahub/tasks/registry.py +6 -4
- infrahub/trigger/catalogue.py +4 -0
- infrahub/trigger/models.py +2 -0
- infrahub/trigger/setup.py +13 -4
- infrahub/trigger/tasks.py +6 -0
- infrahub/webhook/models.py +1 -1
- infrahub/workers/dependencies.py +3 -1
- infrahub/workers/infrahub_async.py +5 -1
- infrahub/workflows/catalogue.py +118 -3
- infrahub/workflows/initialization.py +21 -0
- infrahub/workflows/models.py +17 -2
- infrahub_sdk/branch.py +17 -8
- infrahub_sdk/checks.py +1 -1
- infrahub_sdk/client.py +376 -95
- infrahub_sdk/config.py +29 -2
- infrahub_sdk/convert_object_type.py +61 -0
- infrahub_sdk/ctl/branch.py +3 -0
- infrahub_sdk/ctl/check.py +2 -3
- infrahub_sdk/ctl/cli_commands.py +20 -12
- infrahub_sdk/ctl/config.py +8 -2
- infrahub_sdk/ctl/generator.py +6 -3
- infrahub_sdk/ctl/graphql.py +184 -0
- infrahub_sdk/ctl/repository.py +39 -1
- infrahub_sdk/ctl/schema.py +40 -10
- infrahub_sdk/ctl/task.py +110 -0
- infrahub_sdk/ctl/utils.py +4 -0
- infrahub_sdk/ctl/validate.py +5 -3
- infrahub_sdk/diff.py +4 -5
- infrahub_sdk/exceptions.py +2 -0
- infrahub_sdk/generator.py +7 -1
- infrahub_sdk/graphql/__init__.py +12 -0
- infrahub_sdk/graphql/constants.py +1 -0
- infrahub_sdk/graphql/plugin.py +85 -0
- infrahub_sdk/graphql/query.py +77 -0
- infrahub_sdk/{graphql.py → graphql/renderers.py} +88 -75
- infrahub_sdk/graphql/utils.py +40 -0
- infrahub_sdk/node/attribute.py +2 -0
- infrahub_sdk/node/node.py +28 -20
- infrahub_sdk/node/relationship.py +1 -3
- infrahub_sdk/playback.py +1 -2
- infrahub_sdk/protocols.py +54 -6
- infrahub_sdk/pytest_plugin/plugin.py +7 -4
- infrahub_sdk/pytest_plugin/utils.py +40 -0
- infrahub_sdk/repository.py +1 -2
- infrahub_sdk/schema/__init__.py +70 -4
- infrahub_sdk/schema/main.py +1 -0
- infrahub_sdk/schema/repository.py +8 -0
- infrahub_sdk/spec/models.py +7 -0
- infrahub_sdk/spec/object.py +54 -6
- infrahub_sdk/spec/processors/__init__.py +0 -0
- infrahub_sdk/spec/processors/data_processor.py +10 -0
- infrahub_sdk/spec/processors/factory.py +34 -0
- infrahub_sdk/spec/processors/range_expand_processor.py +56 -0
- infrahub_sdk/spec/range_expansion.py +118 -0
- infrahub_sdk/task/models.py +6 -4
- infrahub_sdk/timestamp.py +18 -6
- infrahub_sdk/transforms.py +1 -1
- {infrahub_server-1.4.13.dist-info → infrahub_server-1.5.0.dist-info}/METADATA +9 -10
- {infrahub_server-1.4.13.dist-info → infrahub_server-1.5.0.dist-info}/RECORD +221 -165
- infrahub_testcontainers/container.py +114 -2
- infrahub_testcontainers/docker-compose-cluster.test.yml +5 -0
- infrahub_testcontainers/docker-compose.test.yml +5 -0
- infrahub_testcontainers/models.py +2 -2
- infrahub_testcontainers/performance_test.py +4 -4
- infrahub/core/convert_object_type/conversion.py +0 -134
- {infrahub_server-1.4.13.dist-info → infrahub_server-1.5.0.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.4.13.dist-info → infrahub_server-1.5.0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.4.13.dist-info → infrahub_server-1.5.0.dist-info}/entry_points.txt +0 -0
infrahub/graphql/manager.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import hashlib
|
|
3
4
|
from dataclasses import dataclass
|
|
4
5
|
from typing import TYPE_CHECKING, Any, Iterable
|
|
5
6
|
|
|
@@ -17,9 +18,9 @@ from infrahub.core.schema import (
|
|
|
17
18
|
RelationshipSchema,
|
|
18
19
|
TemplateSchema,
|
|
19
20
|
)
|
|
20
|
-
from infrahub.core.timestamp import Timestamp
|
|
21
21
|
from infrahub.graphql.mutations.attribute import BaseAttributeCreate, BaseAttributeUpdate
|
|
22
22
|
from infrahub.graphql.mutations.graphql_query import InfrahubGraphQLQueryMutation
|
|
23
|
+
from infrahub.graphql.mutations.profile import InfrahubProfileMutation
|
|
23
24
|
from infrahub.types import ATTRIBUTE_TYPES, InfrahubDataType, get_attribute_type
|
|
24
25
|
|
|
25
26
|
from .directives import DIRECTIVES
|
|
@@ -40,6 +41,7 @@ from .mutations.resource_manager import (
|
|
|
40
41
|
InfrahubNumberPoolMutation,
|
|
41
42
|
)
|
|
42
43
|
from .mutations.webhook import InfrahubWebhookMutation
|
|
44
|
+
from .registry import registry
|
|
43
45
|
from .resolvers.ipam import ipam_paginated_list_resolver
|
|
44
46
|
from .resolvers.resolver import (
|
|
45
47
|
account_resolver,
|
|
@@ -69,7 +71,6 @@ from .types.event import EVENT_TYPES
|
|
|
69
71
|
if TYPE_CHECKING:
|
|
70
72
|
from graphql import GraphQLSchema
|
|
71
73
|
|
|
72
|
-
from infrahub.core.branch import Branch
|
|
73
74
|
from infrahub.core.schema.schema_branch import SchemaBranch
|
|
74
75
|
|
|
75
76
|
|
|
@@ -93,81 +94,34 @@ class GraphqlMutations:
|
|
|
93
94
|
delete: type[InfrahubMutation]
|
|
94
95
|
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
@dataclass
|
|
98
|
+
class InterfaceReference:
|
|
99
|
+
reference: type[graphene.Interface]
|
|
100
|
+
reference_hash: str
|
|
100
101
|
|
|
101
102
|
|
|
102
103
|
@dataclass
|
|
103
|
-
class
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
schema_hash: str
|
|
107
|
-
gql_manager: GraphQLSchemaManager
|
|
104
|
+
class InfrahubObjectReference:
|
|
105
|
+
reference: type[InfrahubObject]
|
|
106
|
+
reference_hash: str
|
|
108
107
|
|
|
109
108
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
"""Return inactive branches that were purged"""
|
|
121
|
-
inactive_branches: set[str] = set()
|
|
122
|
-
for branch_name in list(cls._branch_details_by_name):
|
|
123
|
-
if branch_name not in active_branches:
|
|
124
|
-
inactive_branches.add(branch_name)
|
|
125
|
-
del cls._branch_details_by_name[branch_name]
|
|
126
|
-
return inactive_branches
|
|
127
|
-
|
|
128
|
-
@classmethod
|
|
129
|
-
def _cache_branch(
|
|
130
|
-
cls, branch: Branch, schema_branch: SchemaBranch, schema_hash: str | None = None
|
|
131
|
-
) -> BranchDetails:
|
|
132
|
-
if not schema_hash:
|
|
133
|
-
if branch.schema_hash:
|
|
134
|
-
schema_hash = branch.schema_hash.main
|
|
135
|
-
else:
|
|
136
|
-
schema_hash = schema_branch.get_hash()
|
|
137
|
-
branch_details = BranchDetails(
|
|
138
|
-
branch_name=branch.name,
|
|
139
|
-
schema_changed_at=Timestamp(branch.schema_changed_at) if branch.schema_changed_at else Timestamp(),
|
|
140
|
-
schema_hash=schema_hash,
|
|
141
|
-
gql_manager=cls(schema=schema_branch),
|
|
142
|
-
)
|
|
143
|
-
cls._branch_details_by_name[branch.name] = branch_details
|
|
144
|
-
return branch_details
|
|
145
|
-
|
|
146
|
-
@classmethod
|
|
147
|
-
def get_manager_for_branch(cls, branch: Branch, schema_branch: SchemaBranch) -> GraphQLSchemaManager:
|
|
148
|
-
if branch.name not in cls._branch_details_by_name:
|
|
149
|
-
branch_details = cls._cache_branch(branch=branch, schema_branch=schema_branch)
|
|
150
|
-
return branch_details.gql_manager
|
|
151
|
-
cached_branch_details = cls._branch_details_by_name[branch.name]
|
|
152
|
-
# try to use the schema_changed_at time b/c it is faster than checking the hash
|
|
153
|
-
if branch.schema_changed_at:
|
|
154
|
-
changed_at_time = Timestamp(branch.schema_changed_at)
|
|
155
|
-
if changed_at_time > cached_branch_details.schema_changed_at:
|
|
156
|
-
cached_branch_details = cls._cache_branch(branch=branch, schema_branch=schema_branch)
|
|
157
|
-
return cached_branch_details.gql_manager
|
|
158
|
-
if branch.schema_hash:
|
|
159
|
-
current_hash = branch.active_schema_hash.main
|
|
160
|
-
else:
|
|
161
|
-
current_hash = schema_branch.get_hash()
|
|
162
|
-
if cached_branch_details.schema_hash != current_hash:
|
|
163
|
-
cached_branch_details = cls._cache_branch(
|
|
164
|
-
branch=branch, schema_branch=schema_branch, schema_hash=current_hash
|
|
165
|
-
)
|
|
109
|
+
@dataclass
|
|
110
|
+
class InfrahubEdgedReference:
|
|
111
|
+
reference: type[InfrahubObject]
|
|
112
|
+
reference_hash: str
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def get_attr_kind(node_schema: MainSchemaTypes, attr_schema: AttributeSchema) -> str:
|
|
116
|
+
if not config.SETTINGS.experimental_features.graphql_enums or not attr_schema.enum:
|
|
117
|
+
return attr_schema.kind
|
|
118
|
+
return get_enum_attribute_type_name(node_schema=node_schema, attr_schema=attr_schema)
|
|
166
119
|
|
|
167
|
-
return cached_branch_details.gql_manager
|
|
168
120
|
|
|
121
|
+
class GraphQLSchemaManager:
|
|
169
122
|
def __init__(self, schema: SchemaBranch) -> None:
|
|
170
123
|
self.schema = schema
|
|
124
|
+
self.schema_hash = schema.get_hash()
|
|
171
125
|
|
|
172
126
|
self._full_graphql_schema: GraphQLSchema | None = None
|
|
173
127
|
self._graphql_types: dict[str, GraphQLTypes] = {}
|
|
@@ -275,9 +229,7 @@ class GraphQLSchemaManager:
|
|
|
275
229
|
raise ValueError(f"Unable to find {name!r}")
|
|
276
230
|
|
|
277
231
|
def get_all(self) -> dict[str, GraphQLTypes]:
|
|
278
|
-
|
|
279
|
-
infrahub_types.update(self._extra_types)
|
|
280
|
-
return infrahub_types
|
|
232
|
+
return self._graphql_types
|
|
281
233
|
|
|
282
234
|
def set_type(self, name: str, graphql_type: GraphQLTypes) -> None:
|
|
283
235
|
self._graphql_types[name] = graphql_type
|
|
@@ -342,7 +294,9 @@ class GraphQLSchemaManager:
|
|
|
342
294
|
)
|
|
343
295
|
ATTRIBUTE_TYPES[base_enum_name] = data_type_class
|
|
344
296
|
|
|
345
|
-
def _get_related_input_type(
|
|
297
|
+
def _get_related_input_type(
|
|
298
|
+
self, relationship: RelationshipSchema
|
|
299
|
+
) -> type[RelatedNodeInput | RelatedIPPrefixNodeInput | RelatedIPAddressNodeInput]:
|
|
346
300
|
peer_schema = self.schema.get(name=relationship.peer, duplicate=False)
|
|
347
301
|
if peer_schema.is_ip_prefix:
|
|
348
302
|
return RelatedIPPrefixNodeInput
|
|
@@ -400,12 +354,15 @@ class GraphQLSchemaManager:
|
|
|
400
354
|
# Generate all GraphQL ObjectType, Nested, Paginated & NestedPaginated and store them in the registry
|
|
401
355
|
for node_schema in full_schema.values():
|
|
402
356
|
if isinstance(node_schema, NodeSchema | ProfileSchema | TemplateSchema):
|
|
403
|
-
|
|
357
|
+
node_object_type = self.generate_graphql_object(schema=node_schema, populate_cache=True)
|
|
404
358
|
node_type_edged = self.generate_graphql_edged_object(
|
|
405
|
-
schema=node_schema, node=
|
|
359
|
+
schema=node_schema, node=node_object_type, populate_cache=True
|
|
406
360
|
)
|
|
407
361
|
nested_node_type_edged = self.generate_graphql_edged_object(
|
|
408
|
-
schema=node_schema,
|
|
362
|
+
schema=node_schema,
|
|
363
|
+
node=node_object_type,
|
|
364
|
+
relation_property=relationship_property,
|
|
365
|
+
populate_cache=True,
|
|
409
366
|
)
|
|
410
367
|
|
|
411
368
|
self.generate_graphql_paginated_object(schema=node_schema, edge=node_type_edged, populate_cache=True)
|
|
@@ -533,6 +490,8 @@ class GraphQLSchemaManager:
|
|
|
533
490
|
base_class = InfrahubIPPrefixMutation
|
|
534
491
|
elif isinstance(node_schema, NodeSchema) and node_schema.is_ip_address:
|
|
535
492
|
base_class = InfrahubIPAddressMutation
|
|
493
|
+
elif isinstance(node_schema, ProfileSchema):
|
|
494
|
+
base_class = InfrahubProfileMutation
|
|
536
495
|
else:
|
|
537
496
|
base_class = mutation_map.get(node_schema.kind, InfrahubMutation)
|
|
538
497
|
|
|
@@ -557,13 +516,15 @@ class GraphQLSchemaManager:
|
|
|
557
516
|
|
|
558
517
|
return type("MutationMixin", (object,), class_attrs)
|
|
559
518
|
|
|
560
|
-
def generate_graphql_object(self, schema: MainSchemaTypes, populate_cache: bool = False) ->
|
|
519
|
+
def generate_graphql_object(self, schema: MainSchemaTypes, populate_cache: bool = False) -> InfrahubObjectReference:
|
|
561
520
|
"""Generate a GraphQL object Type from a Infrahub NodeSchema."""
|
|
562
521
|
|
|
563
522
|
interfaces: set[type[InfrahubObject]] = set()
|
|
523
|
+
md5hash = hashlib.md5(usedforsecurity=False)
|
|
524
|
+
md5hash.update(f"{schema.kind}{schema.get_hash()}".encode())
|
|
564
525
|
|
|
565
526
|
if isinstance(schema, NodeSchema | ProfileSchema | TemplateSchema) and schema.inherit_from:
|
|
566
|
-
for generic_name in schema.inherit_from:
|
|
527
|
+
for generic_name in sorted(schema.inherit_from):
|
|
567
528
|
generic = self.get_type(name=generic_name)
|
|
568
529
|
interfaces.add(generic)
|
|
569
530
|
|
|
@@ -597,21 +558,26 @@ class GraphQLSchemaManager:
|
|
|
597
558
|
req = "" if attr.optional else " (required)"
|
|
598
559
|
main_attrs[attr.name] = graphene.Field(attr_type, description=f"{attr.description}{req}")
|
|
599
560
|
|
|
561
|
+
object_hash = md5hash.hexdigest()
|
|
562
|
+
|
|
600
563
|
graphql_object = type(schema.kind, (InfrahubObject,), main_attrs)
|
|
564
|
+
registry.set_object_type(reference=graphql_object, reference_hash=object_hash, schema_hash=self.schema_hash)
|
|
601
565
|
|
|
602
566
|
if populate_cache:
|
|
603
567
|
self.set_type(name=schema.kind, graphql_type=graphql_object)
|
|
604
568
|
|
|
605
|
-
return graphql_object
|
|
569
|
+
return InfrahubObjectReference(reference=graphql_object, reference_hash=object_hash)
|
|
606
570
|
|
|
607
|
-
def generate_interface_object(
|
|
608
|
-
self, schema: GenericSchema, populate_cache: bool = False
|
|
609
|
-
) -> type[graphene.Interface]:
|
|
571
|
+
def generate_interface_object(self, schema: GenericSchema, populate_cache: bool = False) -> InterfaceReference:
|
|
610
572
|
meta_attrs = {
|
|
611
573
|
"name": schema.kind,
|
|
612
574
|
"description": schema.description,
|
|
613
575
|
}
|
|
614
576
|
|
|
577
|
+
md5hash = hashlib.md5(usedforsecurity=False)
|
|
578
|
+
md5hash.update(f"interface-{schema.kind}{schema.get_hash()}".encode())
|
|
579
|
+
interface_hash = md5hash.hexdigest()
|
|
580
|
+
|
|
615
581
|
main_attrs = {
|
|
616
582
|
"id": graphene.Field(graphene.String, required=False, description="Unique identifier"),
|
|
617
583
|
"hfid": graphene.Field(
|
|
@@ -620,7 +586,6 @@ class GraphQLSchemaManager:
|
|
|
620
586
|
description="Human friendly identifier",
|
|
621
587
|
),
|
|
622
588
|
"display_label": graphene.String(required=False),
|
|
623
|
-
"Meta": type("Meta", (object,), meta_attrs),
|
|
624
589
|
}
|
|
625
590
|
|
|
626
591
|
for attr in schema.attributes:
|
|
@@ -628,12 +593,18 @@ class GraphQLSchemaManager:
|
|
|
628
593
|
attr_type = self.get_type(name=get_attribute_type(kind=attr_kind).get_graphql_type_name())
|
|
629
594
|
main_attrs[attr.name] = graphene.Field(attr_type, description=attr.description)
|
|
630
595
|
|
|
631
|
-
interface_object =
|
|
596
|
+
interface_object = registry.get_interface_type(reference_hash=interface_hash, schema_hash=self.schema_hash)
|
|
597
|
+
if not interface_object:
|
|
598
|
+
main_attrs["Meta"] = type("Meta", (object,), meta_attrs)
|
|
599
|
+
interface_object = type(schema.kind, (InfrahubInterface,), main_attrs)
|
|
600
|
+
|
|
601
|
+
interface_reference = InterfaceReference(reference=interface_object, reference_hash=interface_hash)
|
|
602
|
+
registry.set_interface_type(reference=interface_reference, schema_hash=self.schema_hash)
|
|
632
603
|
|
|
633
604
|
if populate_cache:
|
|
634
605
|
self.set_type(name=schema.kind, graphql_type=interface_object)
|
|
635
606
|
|
|
636
|
-
return
|
|
607
|
+
return interface_reference
|
|
637
608
|
|
|
638
609
|
def define_relationship_property(self, data_source: type[InfrahubObject], data_owner: type[InfrahubObject]) -> None:
|
|
639
610
|
type_name = "RelationshipProperty"
|
|
@@ -721,7 +692,18 @@ class GraphQLSchemaManager:
|
|
|
721
692
|
elif rel.cardinality == RelationshipCardinality.MANY:
|
|
722
693
|
attrs[rel.name] = graphene.InputField(graphene.List(input_type), description=rel.description)
|
|
723
694
|
|
|
724
|
-
|
|
695
|
+
input_name = f"{schema.kind}CreateInput"
|
|
696
|
+
md5hash = hashlib.md5(usedforsecurity=False)
|
|
697
|
+
md5hash.update(f"{input_name}{schema.get_hash()}".encode())
|
|
698
|
+
input_hash = md5hash.hexdigest()
|
|
699
|
+
mutation_input_type = registry.get_input_type(reference_hash=input_hash, schema_hash=self.schema_hash)
|
|
700
|
+
if not mutation_input_type:
|
|
701
|
+
mutation_input_type = type(input_name, (graphene.InputObjectType,), attrs)
|
|
702
|
+
registry.set_input_type(
|
|
703
|
+
reference=mutation_input_type, reference_hash=input_hash, schema_hash=self.schema_hash
|
|
704
|
+
)
|
|
705
|
+
|
|
706
|
+
return mutation_input_type
|
|
725
707
|
|
|
726
708
|
def generate_graphql_mutation_update_input(self, schema: MainSchemaTypes) -> type[graphene.InputObjectType]:
|
|
727
709
|
"""Generate an InputObjectType Object from a Infrahub NodeSchema
|
|
@@ -734,7 +716,7 @@ class GraphQLSchemaManager:
|
|
|
734
716
|
slug = InputField(StringAttributeUpdate, required=False)
|
|
735
717
|
description = InputField(StringAttributeUpdate, required=False)
|
|
736
718
|
"""
|
|
737
|
-
attrs: dict[str, graphene.String | graphene.InputField] = {
|
|
719
|
+
attrs: dict[str, graphene.String | graphene.InputField | graphene.List] = {
|
|
738
720
|
"id": graphene.String(required=False),
|
|
739
721
|
"hfid": graphene.List(of_type=graphene.String, required=False),
|
|
740
722
|
}
|
|
@@ -760,7 +742,18 @@ class GraphQLSchemaManager:
|
|
|
760
742
|
graphene.List(input_type), required=False, description=rel.description
|
|
761
743
|
)
|
|
762
744
|
|
|
763
|
-
|
|
745
|
+
input_name = f"{schema.kind}UpdateInput"
|
|
746
|
+
md5hash = hashlib.md5(usedforsecurity=False)
|
|
747
|
+
md5hash.update(f"{input_name}{schema.get_hash()}".encode())
|
|
748
|
+
input_hash = md5hash.hexdigest()
|
|
749
|
+
mutation_input_type = registry.get_input_type(reference_hash=input_hash, schema_hash=self.schema_hash)
|
|
750
|
+
if not mutation_input_type:
|
|
751
|
+
mutation_input_type = type(input_name, (graphene.InputObjectType,), attrs)
|
|
752
|
+
registry.set_input_type(
|
|
753
|
+
reference=mutation_input_type, reference_hash=input_hash, schema_hash=self.schema_hash
|
|
754
|
+
)
|
|
755
|
+
|
|
756
|
+
return mutation_input_type
|
|
764
757
|
|
|
765
758
|
def generate_graphql_mutation_upsert_input(
|
|
766
759
|
self, schema: NodeSchema | ProfileSchema | TemplateSchema
|
|
@@ -775,7 +768,7 @@ class GraphQLSchemaManager:
|
|
|
775
768
|
slug = InputField(StringAttributeUpdate, required=True)
|
|
776
769
|
description = InputField(StringAttributeUpdate, required=False)
|
|
777
770
|
"""
|
|
778
|
-
attrs: dict[str, graphene.String | graphene.InputField] = {
|
|
771
|
+
attrs: dict[str, graphene.String | graphene.InputField | graphene.List] = {
|
|
779
772
|
"id": graphene.String(required=False),
|
|
780
773
|
"hfid": graphene.List(of_type=graphene.String, required=False),
|
|
781
774
|
}
|
|
@@ -801,7 +794,18 @@ class GraphQLSchemaManager:
|
|
|
801
794
|
elif rel.cardinality == RelationshipCardinality.MANY:
|
|
802
795
|
attrs[rel.name] = graphene.InputField(graphene.List(input_type), description=rel.description)
|
|
803
796
|
|
|
804
|
-
|
|
797
|
+
input_name = f"{schema.kind}UpsertInput"
|
|
798
|
+
md5hash = hashlib.md5(usedforsecurity=False)
|
|
799
|
+
md5hash.update(f"{input_name}{schema.get_hash()}".encode())
|
|
800
|
+
input_hash = md5hash.hexdigest()
|
|
801
|
+
mutation_input_type = registry.get_input_type(reference_hash=input_hash, schema_hash=self.schema_hash)
|
|
802
|
+
if not mutation_input_type:
|
|
803
|
+
mutation_input_type = type(input_name, (graphene.InputObjectType,), attrs)
|
|
804
|
+
registry.set_input_type(
|
|
805
|
+
reference=mutation_input_type, reference_hash=input_hash, schema_hash=self.schema_hash
|
|
806
|
+
)
|
|
807
|
+
|
|
808
|
+
return mutation_input_type
|
|
805
809
|
|
|
806
810
|
def generate_graphql_mutation_create(
|
|
807
811
|
self,
|
|
@@ -813,17 +817,27 @@ class GraphQLSchemaManager:
|
|
|
813
817
|
"""Generate a GraphQL Mutation to CREATE an object based on the specified NodeSchema."""
|
|
814
818
|
name = f"{schema.kind}{mutation_type}"
|
|
815
819
|
|
|
816
|
-
|
|
820
|
+
md5hash = hashlib.md5(usedforsecurity=False)
|
|
821
|
+
md5hash.update(f"{name}{schema.get_hash()}".encode())
|
|
822
|
+
mutation_hash = md5hash.hexdigest()
|
|
817
823
|
|
|
818
|
-
|
|
824
|
+
mutation_object = registry.get_mutation_type(reference_hash=mutation_hash, schema_hash=self.schema_hash)
|
|
825
|
+
if not mutation_object:
|
|
826
|
+
object_type = self.generate_graphql_object(schema=schema)
|
|
819
827
|
|
|
820
|
-
|
|
821
|
-
main_attrs["Meta"] = type("Meta", (object,), meta_attrs)
|
|
828
|
+
main_attrs: dict[str, Any] = {"ok": graphene.Boolean(), "object": graphene.Field(object_type.reference)}
|
|
822
829
|
|
|
823
|
-
|
|
824
|
-
|
|
830
|
+
meta_attrs: dict[str, Any] = {"schema": schema, "name": name, "description": schema.description}
|
|
831
|
+
main_attrs["Meta"] = type("Meta", (object,), meta_attrs)
|
|
825
832
|
|
|
826
|
-
|
|
833
|
+
args_attrs = {"data": input_type(required=True), "context": ContextInput(required=False)}
|
|
834
|
+
main_attrs["Arguments"] = type("Arguments", (object,), args_attrs)
|
|
835
|
+
mutation_object = type(name, (base_class,), main_attrs)
|
|
836
|
+
registry.set_mutation_type(
|
|
837
|
+
reference=mutation_object, reference_hash=mutation_hash, schema_hash=self.schema_hash
|
|
838
|
+
)
|
|
839
|
+
|
|
840
|
+
return mutation_object
|
|
827
841
|
|
|
828
842
|
def generate_graphql_mutation_update(
|
|
829
843
|
self,
|
|
@@ -834,34 +848,50 @@ class GraphQLSchemaManager:
|
|
|
834
848
|
"""Generate a GraphQL Mutation to UPDATE an object based on the specified NodeSchema."""
|
|
835
849
|
name = f"{schema.kind}Update"
|
|
836
850
|
|
|
837
|
-
|
|
851
|
+
md5hash = hashlib.md5(usedforsecurity=False)
|
|
852
|
+
md5hash.update(f"{name}{schema.get_hash()}".encode())
|
|
853
|
+
mutation_hash = md5hash.hexdigest()
|
|
838
854
|
|
|
839
|
-
|
|
855
|
+
mutation_object = registry.get_mutation_type(reference_hash=mutation_hash, schema_hash=self.schema_hash)
|
|
856
|
+
if not mutation_object:
|
|
857
|
+
object_type = self.generate_graphql_object(schema=schema)
|
|
840
858
|
|
|
841
|
-
|
|
842
|
-
main_attrs["Meta"] = type("Meta", (object,), meta_attrs)
|
|
859
|
+
main_attrs: dict[str, Any] = {"ok": graphene.Boolean(), "object": graphene.Field(object_type.reference)}
|
|
843
860
|
|
|
844
|
-
|
|
845
|
-
|
|
861
|
+
meta_attrs: dict[str, Any] = {"schema": schema, "name": name, "description": schema.description}
|
|
862
|
+
main_attrs["Meta"] = type("Meta", (object,), meta_attrs)
|
|
846
863
|
|
|
847
|
-
|
|
864
|
+
args_attrs = {"data": input_type(required=True), "context": ContextInput(required=False)}
|
|
865
|
+
main_attrs["Arguments"] = type("Arguments", (object,), args_attrs)
|
|
866
|
+
|
|
867
|
+
mutation_object = type(name, (base_class,), main_attrs)
|
|
868
|
+
registry.set_mutation_type(
|
|
869
|
+
reference=mutation_object, reference_hash=mutation_hash, schema_hash=self.schema_hash
|
|
870
|
+
)
|
|
871
|
+
|
|
872
|
+
return mutation_object
|
|
848
873
|
|
|
849
|
-
@staticmethod
|
|
850
874
|
def generate_graphql_mutation_delete(
|
|
851
|
-
schema: NodeSchema | ProfileSchema | TemplateSchema, base_class: type[InfrahubMutation] = InfrahubMutation
|
|
875
|
+
self, schema: NodeSchema | ProfileSchema | TemplateSchema, base_class: type[InfrahubMutation] = InfrahubMutation
|
|
852
876
|
) -> type[InfrahubMutation]:
|
|
853
877
|
"""Generate a GraphQL Mutation to DELETE an object based on the specified NodeSchema."""
|
|
854
878
|
name = f"{schema.kind}Delete"
|
|
879
|
+
md5hash = hashlib.md5(usedforsecurity=False)
|
|
880
|
+
md5hash.update(f"{name}{schema.get_hash()}".encode())
|
|
881
|
+
mutation_hash = md5hash.hexdigest()
|
|
882
|
+
mutation_object = registry.get_mutation_type(reference_hash=mutation_hash, schema_hash=self.schema_hash)
|
|
883
|
+
if not mutation_object:
|
|
884
|
+
main_attrs: dict[str, Any] = {"ok": graphene.Boolean()}
|
|
885
|
+
meta_attrs = {"schema": schema, "name": name, "description": schema.description}
|
|
886
|
+
main_attrs["Meta"] = type("Meta", (object,), meta_attrs)
|
|
887
|
+
args_attrs: dict[str, Any] = {"data": DeleteInput(required=True), "context": ContextInput(required=False)}
|
|
888
|
+
main_attrs["Arguments"] = type("Arguments", (object,), args_attrs)
|
|
889
|
+
mutation_object = type(name, (base_class,), main_attrs)
|
|
890
|
+
registry.set_mutation_type(
|
|
891
|
+
reference=mutation_object, reference_hash=mutation_hash, schema_hash=self.schema_hash
|
|
892
|
+
)
|
|
855
893
|
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
meta_attrs = {"schema": schema, "name": name, "description": schema.description}
|
|
859
|
-
main_attrs["Meta"] = type("Meta", (object,), meta_attrs)
|
|
860
|
-
|
|
861
|
-
args_attrs: dict[str, Any] = {"data": DeleteInput(required=True), "context": ContextInput(required=False)}
|
|
862
|
-
main_attrs["Arguments"] = type("Arguments", (object,), args_attrs)
|
|
863
|
-
|
|
864
|
-
return type(name, (base_class,), main_attrs)
|
|
894
|
+
return mutation_object
|
|
865
895
|
|
|
866
896
|
def generate_filters(
|
|
867
897
|
self, schema: MainSchemaTypes, top_level: bool = False, include_properties: bool = True
|
|
@@ -934,16 +964,20 @@ class GraphQLSchemaManager:
|
|
|
934
964
|
def generate_graphql_edged_object(
|
|
935
965
|
self,
|
|
936
966
|
schema: MainSchemaTypes,
|
|
937
|
-
node:
|
|
967
|
+
node: InterfaceReference | InfrahubObjectReference,
|
|
938
968
|
relation_property: type[InfrahubObject] | None = None,
|
|
939
969
|
populate_cache: bool = False,
|
|
940
|
-
) ->
|
|
970
|
+
) -> InfrahubEdgedReference:
|
|
941
971
|
"""Generate a edged GraphQL object Type from a Infrahub NodeSchema for pagination."""
|
|
942
972
|
|
|
943
973
|
object_name = f"Edged{schema.kind}"
|
|
944
974
|
if relation_property:
|
|
945
975
|
object_name = f"NestedEdged{schema.kind}"
|
|
946
976
|
|
|
977
|
+
md5hash = hashlib.md5(usedforsecurity=False)
|
|
978
|
+
md5hash.update(f"{object_name}{schema.get_hash()}{node.reference_hash}".encode())
|
|
979
|
+
edge_hash = md5hash.hexdigest()
|
|
980
|
+
|
|
947
981
|
meta_attrs: dict[str, Any] = {
|
|
948
982
|
"schema": schema,
|
|
949
983
|
"name": object_name,
|
|
@@ -952,22 +986,27 @@ class GraphQLSchemaManager:
|
|
|
952
986
|
}
|
|
953
987
|
|
|
954
988
|
main_attrs: dict[str, Any] = {
|
|
955
|
-
"node": graphene.Field(node, required=False),
|
|
989
|
+
"node": graphene.Field(node.reference, required=False),
|
|
956
990
|
"Meta": type("Meta", (object,), meta_attrs),
|
|
957
991
|
}
|
|
958
992
|
|
|
959
993
|
if relation_property:
|
|
960
994
|
main_attrs["properties"] = graphene.Field(relation_property, required=False)
|
|
961
995
|
|
|
962
|
-
graphql_edged_object =
|
|
996
|
+
graphql_edged_object = registry.get_edge_type(reference_hash=edge_hash, schema_hash=self.schema_hash)
|
|
997
|
+
if not graphql_edged_object:
|
|
998
|
+
graphql_edged_object = type(object_name, (InfrahubObject,), main_attrs)
|
|
999
|
+
registry.set_edge_type(
|
|
1000
|
+
reference=graphql_edged_object, reference_hash=edge_hash, schema_hash=self.schema_hash
|
|
1001
|
+
)
|
|
963
1002
|
|
|
964
1003
|
if populate_cache:
|
|
965
1004
|
self.set_type(name=object_name, graphql_type=graphql_edged_object)
|
|
966
1005
|
|
|
967
|
-
return graphql_edged_object
|
|
1006
|
+
return InfrahubEdgedReference(reference=graphql_edged_object, reference_hash=edge_hash)
|
|
968
1007
|
|
|
969
1008
|
def generate_graphql_paginated_object(
|
|
970
|
-
self, schema: MainSchemaTypes, edge:
|
|
1009
|
+
self, schema: MainSchemaTypes, edge: InfrahubEdgedReference, nested: bool = False, populate_cache: bool = False
|
|
971
1010
|
) -> type[InfrahubObject]:
|
|
972
1011
|
"""Generate a paginated GraphQL object Type from a Infrahub NodeSchema."""
|
|
973
1012
|
|
|
@@ -975,6 +1014,10 @@ class GraphQLSchemaManager:
|
|
|
975
1014
|
if nested:
|
|
976
1015
|
object_name = f"NestedPaginated{schema.kind}"
|
|
977
1016
|
|
|
1017
|
+
md5hash = hashlib.md5(usedforsecurity=False)
|
|
1018
|
+
md5hash.update(f"{object_name}{schema.get_hash()}{edge.reference_hash}".encode())
|
|
1019
|
+
paginated_hash = md5hash.hexdigest()
|
|
1020
|
+
|
|
978
1021
|
meta_attrs: dict[str, Any] = {
|
|
979
1022
|
"schema": schema,
|
|
980
1023
|
"name": object_name,
|
|
@@ -985,14 +1028,21 @@ class GraphQLSchemaManager:
|
|
|
985
1028
|
|
|
986
1029
|
main_attrs: dict[str, Any] = {
|
|
987
1030
|
"count": graphene.Int(required=True),
|
|
988
|
-
"edges": graphene.List(of_type=graphene.NonNull(edge), required=True),
|
|
1031
|
+
"edges": graphene.List(of_type=graphene.NonNull(edge.reference), required=True),
|
|
989
1032
|
"permissions": graphene.Field(
|
|
990
1033
|
PaginatedObjectPermission, required=True, resolver=parent_field_name_resolver
|
|
991
1034
|
),
|
|
992
|
-
"Meta": type("Meta", (object,), meta_attrs),
|
|
993
1035
|
}
|
|
994
1036
|
|
|
995
|
-
graphql_paginated_object =
|
|
1037
|
+
graphql_paginated_object = registry.get_paginated_type(
|
|
1038
|
+
reference_hash=paginated_hash, schema_hash=self.schema_hash
|
|
1039
|
+
)
|
|
1040
|
+
if not graphql_paginated_object:
|
|
1041
|
+
main_attrs["Meta"] = type("Meta", (object,), meta_attrs)
|
|
1042
|
+
graphql_paginated_object = type(object_name, (InfrahubObject,), main_attrs)
|
|
1043
|
+
registry.set_paginated_type(
|
|
1044
|
+
reference=graphql_paginated_object, reference_hash=paginated_hash, schema_hash=self.schema_hash
|
|
1045
|
+
)
|
|
996
1046
|
|
|
997
1047
|
if populate_cache:
|
|
998
1048
|
self.set_type(name=object_name, graphql_type=graphql_paginated_object)
|
|
@@ -1022,27 +1072,53 @@ class GraphQLSchemaManager:
|
|
|
1022
1072
|
main_attrs["properties"] = graphene.Field(relation_property, required=False)
|
|
1023
1073
|
|
|
1024
1074
|
object_name = f"NestedEdged{schema.kind}"
|
|
1025
|
-
|
|
1075
|
+
md5hash = hashlib.md5(usedforsecurity=False)
|
|
1076
|
+
md5hash.update(f"{object_name}{schema.get_hash()}".encode())
|
|
1077
|
+
paginated_hash = md5hash.hexdigest()
|
|
1078
|
+
nested_interface_object = registry.get_paginated_type(
|
|
1079
|
+
reference_hash=paginated_hash, schema_hash=self.schema_hash
|
|
1080
|
+
)
|
|
1081
|
+
if not nested_interface_object:
|
|
1082
|
+
nested_interface_object = type(object_name, (InfrahubObject,), main_attrs)
|
|
1083
|
+
registry.set_paginated_type(
|
|
1084
|
+
reference=nested_interface_object, reference_hash=paginated_hash, schema_hash=self.schema_hash
|
|
1085
|
+
)
|
|
1026
1086
|
|
|
1027
1087
|
if populate_cache:
|
|
1028
1088
|
self.set_type(name=object_name, graphql_type=nested_interface_object)
|
|
1029
1089
|
|
|
1030
1090
|
return nested_interface_object
|
|
1031
1091
|
|
|
1032
|
-
@staticmethod
|
|
1033
1092
|
def generate_paginated_interface_object(
|
|
1034
|
-
schema: GenericSchema, base_interface: type[graphene.ObjectType]
|
|
1093
|
+
self, schema: GenericSchema, base_interface: type[graphene.ObjectType]
|
|
1035
1094
|
) -> type[InfrahubObject]:
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1095
|
+
object_name = f"NestedPaginated{schema.kind}"
|
|
1096
|
+
md5hash = hashlib.md5(usedforsecurity=False)
|
|
1097
|
+
md5hash.update(f"{object_name}{schema.get_hash()}".encode())
|
|
1098
|
+
paginated_hash = md5hash.hexdigest()
|
|
1099
|
+
|
|
1100
|
+
nested_interface_object = registry.get_paginated_type(
|
|
1101
|
+
reference_hash=paginated_hash, schema_hash=self.schema_hash
|
|
1102
|
+
)
|
|
1103
|
+
if not nested_interface_object:
|
|
1104
|
+
meta_attrs: dict[str, Any] = {
|
|
1105
|
+
"name": object_name,
|
|
1106
|
+
"schema": schema,
|
|
1107
|
+
"description": schema.description,
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
main_attrs: dict[str, Any] = {
|
|
1111
|
+
"count": graphene.Int(required=True),
|
|
1112
|
+
"edges": graphene.List(of_type=graphene.NonNull(base_interface)),
|
|
1113
|
+
"Meta": type("Meta", (object,), meta_attrs),
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
nested_interface_object = type(object_name, (InfrahubObject,), main_attrs)
|
|
1117
|
+
registry.set_paginated_type(
|
|
1118
|
+
reference=nested_interface_object, reference_hash=paginated_hash, schema_hash=self.schema_hash
|
|
1119
|
+
)
|
|
1120
|
+
|
|
1121
|
+
return nested_interface_object
|
|
1041
1122
|
|
|
1042
|
-
main_attrs: dict[str, Any] = {
|
|
1043
|
-
"count": graphene.Int(required=True),
|
|
1044
|
-
"edges": graphene.List(of_type=graphene.NonNull(base_interface)),
|
|
1045
|
-
"Meta": type("Meta", (object,), meta_attrs),
|
|
1046
|
-
}
|
|
1047
1123
|
|
|
1048
|
-
|
|
1124
|
+
registry._register_manager(manager=GraphQLSchemaManager)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from infrahub.core.branch.needs_rebase_status import check_need_rebase_status
|
|
2
|
+
|
|
3
|
+
ALLOWED_MUTATIONS_ON_NEED_REBASE_BRANCH = ["BranchRebase", "BranchDelete", "BranchCreate", "ProposedChangeCreate"]
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def raise_on_mutation_on_branch_needing_rebase(next, root, info, **kwargs): # type: ignore # noqa
|
|
7
|
+
if info.operation.operation.value == "mutation":
|
|
8
|
+
mutation_name = info.operation.selection_set.selections[0].name.value
|
|
9
|
+
if mutation_name not in ALLOWED_MUTATIONS_ON_NEED_REBASE_BRANCH:
|
|
10
|
+
check_need_rebase_status(branch=info.context.branch)
|
|
11
|
+
|
|
12
|
+
return next(root, info, **kwargs)
|
|
@@ -7,8 +7,11 @@ from opentelemetry import trace
|
|
|
7
7
|
from typing_extensions import Self
|
|
8
8
|
|
|
9
9
|
from infrahub.branch.merge_mutation_checker import verify_branch_merge_mutation_allowed
|
|
10
|
+
from infrahub.core import registry
|
|
10
11
|
from infrahub.core.branch import Branch
|
|
12
|
+
from infrahub.core.branch.enums import BranchStatus
|
|
11
13
|
from infrahub.database import retry_db_transaction
|
|
14
|
+
from infrahub.exceptions import BranchNotFoundError, ValidationError
|
|
12
15
|
from infrahub.graphql.context import apply_external_context
|
|
13
16
|
from infrahub.graphql.field_extractor import extract_graphql_fields
|
|
14
17
|
from infrahub.graphql.types.context import ContextInput
|
|
@@ -66,12 +69,21 @@ class BranchCreate(Mutation):
|
|
|
66
69
|
background_execution: bool = False,
|
|
67
70
|
wait_until_completion: bool = True,
|
|
68
71
|
) -> Self:
|
|
72
|
+
if data.origin_branch and data.origin_branch != registry.default_branch:
|
|
73
|
+
raise ValueError(f"origin_branch must be '{registry.default_branch}'")
|
|
74
|
+
|
|
69
75
|
graphql_context: GraphqlContext = info.context
|
|
70
76
|
task: dict | None = None
|
|
71
77
|
|
|
72
78
|
model = BranchCreateModel(**data)
|
|
73
79
|
await apply_external_context(graphql_context=graphql_context, context_input=context)
|
|
74
80
|
|
|
81
|
+
try:
|
|
82
|
+
await Branch.get_by_name(db=graphql_context.db, name=model.name)
|
|
83
|
+
raise ValidationError(f"The branch {model.name} already exists")
|
|
84
|
+
except BranchNotFoundError:
|
|
85
|
+
pass
|
|
86
|
+
|
|
75
87
|
if background_execution or not wait_until_completion:
|
|
76
88
|
workflow = await graphql_context.active_service.workflow.submit_workflow(
|
|
77
89
|
workflow=BRANCH_CREATE, context=graphql_context.get_context(), parameters={"model": model}
|
|
@@ -279,6 +291,10 @@ class BranchMerge(Mutation):
|
|
|
279
291
|
db=graphql_context.db, account_session=graphql_context.active_account_session
|
|
280
292
|
)
|
|
281
293
|
|
|
294
|
+
obj = await Branch.get_by_name(db=graphql_context.db, name=branch_name)
|
|
295
|
+
if obj.status == BranchStatus.NEED_UPGRADE_REBASE:
|
|
296
|
+
raise ValidationError(f"Cannot merge branch '{branch_name}' with status '{obj.status.name}'")
|
|
297
|
+
|
|
282
298
|
if wait_until_completion:
|
|
283
299
|
await graphql_context.active_service.workflow.execute_workflow(
|
|
284
300
|
workflow=BRANCH_MERGE_MUTATION,
|