infrahub-server 1.2.12__py3-none-any.whl → 1.3.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/constants.py +130 -0
- infrahub/actions/gather.py +114 -0
- infrahub/actions/models.py +243 -0
- infrahub/actions/parsers.py +104 -0
- infrahub/actions/schema.py +393 -0
- infrahub/actions/tasks.py +119 -0
- infrahub/actions/triggers.py +21 -0
- infrahub/branch/__init__.py +0 -0
- infrahub/branch/tasks.py +29 -0
- infrahub/branch/triggers.py +22 -0
- infrahub/cli/db.py +3 -4
- infrahub/computed_attribute/gather.py +3 -1
- infrahub/computed_attribute/tasks.py +23 -29
- infrahub/core/account.py +24 -47
- infrahub/core/attribute.py +13 -15
- infrahub/core/constants/__init__.py +10 -0
- infrahub/core/constants/infrahubkind.py +9 -0
- infrahub/core/constraint/node/runner.py +3 -1
- infrahub/core/convert_object_type/__init__.py +0 -0
- infrahub/core/convert_object_type/conversion.py +124 -0
- infrahub/core/convert_object_type/schema_mapping.py +56 -0
- infrahub/core/diff/coordinator.py +8 -1
- infrahub/core/diff/query/all_conflicts.py +1 -5
- infrahub/core/diff/query/artifact.py +10 -20
- infrahub/core/diff/query/delete_query.py +8 -4
- infrahub/core/diff/query/diff_get.py +3 -6
- infrahub/core/diff/query/field_specifiers.py +1 -1
- infrahub/core/diff/query/field_summary.py +2 -4
- infrahub/core/diff/query/merge.py +72 -125
- infrahub/core/diff/query/save.py +28 -43
- infrahub/core/diff/query/summary_counts_enricher.py +34 -54
- infrahub/core/diff/query/time_range_query.py +0 -1
- infrahub/core/diff/repository/repository.py +4 -0
- infrahub/core/manager.py +14 -11
- infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
- infrahub/core/migrations/graph/m012_convert_account_generic.py +1 -1
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -6
- infrahub/core/migrations/graph/m015_diff_format_update.py +1 -2
- infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -2
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +11 -22
- infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -6
- infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +1 -2
- infrahub/core/migrations/graph/m023_deduplicate_cardinality_one_relationships.py +2 -2
- infrahub/core/migrations/graph/m024_missing_hierarchy_backfill.py +1 -2
- infrahub/core/migrations/graph/m028_delete_diffs.py +1 -2
- infrahub/core/migrations/graph/m029_duplicates_cleanup.py +30 -48
- infrahub/core/migrations/graph/m030_illegal_edges.py +1 -2
- infrahub/core/migrations/query/attribute_add.py +1 -2
- infrahub/core/migrations/query/attribute_rename.py +6 -11
- infrahub/core/migrations/query/delete_element_in_schema.py +19 -17
- infrahub/core/migrations/query/node_duplicate.py +19 -21
- infrahub/core/migrations/query/relationship_duplicate.py +19 -18
- infrahub/core/migrations/schema/node_attribute_remove.py +4 -8
- infrahub/core/migrations/schema/node_remove.py +19 -20
- infrahub/core/models.py +29 -2
- infrahub/core/node/__init__.py +131 -28
- infrahub/core/node/base.py +1 -1
- infrahub/core/node/create.py +211 -0
- infrahub/core/node/resource_manager/number_pool.py +31 -5
- infrahub/core/node/standard.py +6 -1
- infrahub/core/path.py +15 -1
- infrahub/core/protocols.py +57 -0
- infrahub/core/protocols_base.py +3 -0
- infrahub/core/query/__init__.py +2 -2
- infrahub/core/query/delete.py +3 -3
- infrahub/core/query/diff.py +19 -32
- infrahub/core/query/ipam.py +10 -20
- infrahub/core/query/node.py +29 -47
- infrahub/core/query/relationship.py +55 -34
- infrahub/core/query/resource_manager.py +1 -2
- infrahub/core/query/standard_node.py +19 -5
- infrahub/core/query/subquery.py +2 -4
- infrahub/core/relationship/constraints/count.py +10 -9
- infrahub/core/relationship/constraints/interface.py +2 -1
- infrahub/core/relationship/constraints/peer_kind.py +2 -1
- infrahub/core/relationship/constraints/peer_parent.py +56 -0
- infrahub/core/relationship/constraints/peer_relatives.py +72 -0
- infrahub/core/relationship/constraints/profiles_kind.py +1 -1
- infrahub/core/relationship/model.py +4 -1
- infrahub/core/schema/__init__.py +2 -1
- infrahub/core/schema/attribute_parameters.py +160 -0
- infrahub/core/schema/attribute_schema.py +130 -7
- infrahub/core/schema/basenode_schema.py +27 -3
- infrahub/core/schema/definitions/core/__init__.py +29 -1
- infrahub/core/schema/definitions/core/group.py +45 -0
- infrahub/core/schema/definitions/core/resource_pool.py +9 -0
- infrahub/core/schema/definitions/internal.py +43 -5
- infrahub/core/schema/generated/attribute_schema.py +16 -3
- infrahub/core/schema/generated/relationship_schema.py +11 -1
- infrahub/core/schema/manager.py +7 -2
- infrahub/core/schema/schema_branch.py +104 -9
- infrahub/core/validators/__init__.py +15 -2
- infrahub/core/validators/attribute/choices.py +1 -3
- infrahub/core/validators/attribute/enum.py +1 -3
- infrahub/core/validators/attribute/kind.py +1 -3
- infrahub/core/validators/attribute/length.py +13 -7
- infrahub/core/validators/attribute/min_max.py +118 -0
- infrahub/core/validators/attribute/number_pool.py +106 -0
- infrahub/core/validators/attribute/optional.py +1 -4
- infrahub/core/validators/attribute/regex.py +5 -6
- infrahub/core/validators/attribute/unique.py +1 -3
- infrahub/core/validators/determiner.py +18 -2
- infrahub/core/validators/enum.py +12 -0
- infrahub/core/validators/node/hierarchy.py +3 -6
- infrahub/core/validators/query.py +1 -3
- infrahub/core/validators/relationship/count.py +6 -12
- infrahub/core/validators/relationship/optional.py +2 -4
- infrahub/core/validators/relationship/peer.py +177 -12
- infrahub/core/validators/tasks.py +1 -1
- infrahub/core/validators/uniqueness/query.py +5 -9
- infrahub/database/__init__.py +12 -4
- infrahub/database/validation.py +1 -2
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +4 -0
- infrahub/dependencies/builder/constraint/relationship_manager/peer_parent.py +8 -0
- infrahub/dependencies/builder/constraint/relationship_manager/peer_relatives.py +8 -0
- infrahub/dependencies/builder/constraint/schema/aggregated.py +2 -0
- infrahub/dependencies/builder/constraint/schema/relationship_peer.py +8 -0
- infrahub/dependencies/builder/diff/deserializer.py +1 -1
- infrahub/dependencies/registry.py +4 -0
- infrahub/events/group_action.py +1 -0
- infrahub/events/models.py +1 -1
- infrahub/git/base.py +5 -3
- infrahub/git/integrator.py +96 -5
- infrahub/git/tasks.py +1 -0
- infrahub/graphql/analyzer.py +139 -18
- infrahub/graphql/manager.py +4 -0
- infrahub/graphql/mutations/action.py +164 -0
- infrahub/graphql/mutations/convert_object_type.py +71 -0
- infrahub/graphql/mutations/main.py +24 -175
- infrahub/graphql/mutations/proposed_change.py +20 -17
- infrahub/graphql/mutations/relationship.py +32 -0
- infrahub/graphql/mutations/resource_manager.py +63 -7
- infrahub/graphql/queries/convert_object_type_mapping.py +34 -0
- infrahub/graphql/queries/resource_manager.py +7 -1
- infrahub/graphql/resolvers/many_relationship.py +1 -1
- infrahub/graphql/resolvers/resolver.py +2 -2
- infrahub/graphql/resolvers/single_relationship.py +1 -1
- infrahub/graphql/schema.py +6 -0
- infrahub/menu/menu.py +34 -2
- infrahub/message_bus/messages/__init__.py +0 -10
- infrahub/message_bus/operations/__init__.py +0 -8
- infrahub/message_bus/operations/refresh/registry.py +3 -6
- infrahub/patch/queries/delete_duplicated_edges.py +10 -15
- infrahub/pools/models.py +14 -0
- infrahub/pools/number.py +5 -3
- infrahub/pools/registration.py +22 -0
- infrahub/pools/tasks.py +126 -0
- infrahub/prefect_server/models.py +1 -19
- infrahub/proposed_change/models.py +68 -3
- infrahub/proposed_change/tasks.py +911 -34
- infrahub/schema/__init__.py +0 -0
- infrahub/schema/tasks.py +27 -0
- infrahub/schema/triggers.py +23 -0
- infrahub/task_manager/models.py +10 -6
- infrahub/trigger/catalogue.py +6 -0
- infrahub/trigger/models.py +23 -6
- infrahub/trigger/setup.py +26 -2
- infrahub/trigger/tasks.py +4 -2
- infrahub/types.py +6 -0
- infrahub/webhook/tasks.py +4 -8
- infrahub/workflows/catalogue.py +103 -1
- infrahub_sdk/client.py +43 -10
- infrahub_sdk/ctl/generator.py +4 -4
- infrahub_sdk/ctl/repository.py +1 -1
- infrahub_sdk/node/__init__.py +39 -0
- infrahub_sdk/node/attribute.py +122 -0
- infrahub_sdk/node/constants.py +21 -0
- infrahub_sdk/{node.py → node/node.py} +158 -803
- infrahub_sdk/node/parsers.py +15 -0
- infrahub_sdk/node/property.py +24 -0
- infrahub_sdk/node/related_node.py +266 -0
- infrahub_sdk/node/relationship.py +302 -0
- infrahub_sdk/protocols.py +112 -0
- infrahub_sdk/protocols_base.py +34 -2
- infrahub_sdk/pytest_plugin/items/python_transform.py +2 -1
- infrahub_sdk/query_groups.py +17 -5
- infrahub_sdk/schema/main.py +1 -0
- infrahub_sdk/schema/repository.py +16 -0
- infrahub_sdk/spec/object.py +1 -1
- infrahub_sdk/store.py +1 -1
- infrahub_sdk/testing/schemas/car_person.py +1 -0
- infrahub_sdk/utils.py +7 -20
- infrahub_sdk/yaml.py +6 -5
- {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/METADATA +3 -3
- {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/RECORD +192 -166
- infrahub_testcontainers/container.py +0 -1
- infrahub_testcontainers/docker-compose.test.yml +1 -1
- infrahub_testcontainers/helpers.py +8 -2
- infrahub/message_bus/messages/check_generator_run.py +0 -26
- infrahub/message_bus/messages/finalize_validator_execution.py +0 -15
- infrahub/message_bus/messages/proposed_change/base_with_diff.py +0 -16
- infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +0 -11
- infrahub/message_bus/messages/request_generatordefinition_check.py +0 -20
- infrahub/message_bus/messages/request_proposedchange_pipeline.py +0 -23
- infrahub/message_bus/operations/check/__init__.py +0 -3
- infrahub/message_bus/operations/check/generator.py +0 -156
- infrahub/message_bus/operations/finalize/__init__.py +0 -3
- infrahub/message_bus/operations/finalize/validator.py +0 -133
- infrahub/message_bus/operations/requests/__init__.py +0 -9
- infrahub/message_bus/operations/requests/generator_definition.py +0 -140
- infrahub/message_bus/operations/requests/proposed_change.py +0 -629
- /infrahub/{message_bus/messages/proposed_change → actions}/__init__.py +0 -0
- {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
|
6
6
|
from graphene import InputObjectType, Mutation
|
|
7
7
|
from graphene.types.mutation import MutationOptions
|
|
@@ -9,12 +9,15 @@ from infrahub_sdk.utils import extract_fields
|
|
|
9
9
|
from typing_extensions import Self
|
|
10
10
|
|
|
11
11
|
from infrahub import config, lock
|
|
12
|
-
from infrahub.core import
|
|
13
|
-
from infrahub.core.constants import InfrahubKind, MutationAction, RelationshipCardinality, RelationshipKind
|
|
12
|
+
from infrahub.core.constants import InfrahubKind, MutationAction
|
|
14
13
|
from infrahub.core.constraint.node.runner import NodeConstraintRunner
|
|
15
14
|
from infrahub.core.manager import NodeManager
|
|
16
|
-
from infrahub.core.node import
|
|
17
|
-
|
|
15
|
+
from infrahub.core.node.create import (
|
|
16
|
+
create_node,
|
|
17
|
+
get_profile_ids,
|
|
18
|
+
refresh_for_profile_update,
|
|
19
|
+
)
|
|
20
|
+
from infrahub.core.schema import MainSchemaTypes, NodeSchema
|
|
18
21
|
from infrahub.core.schema.generic_schema import GenericSchema
|
|
19
22
|
from infrahub.core.schema.profile_schema import ProfileSchema
|
|
20
23
|
from infrahub.core.schema.template_schema import TemplateSchema
|
|
@@ -33,8 +36,7 @@ if TYPE_CHECKING:
|
|
|
33
36
|
from graphql import GraphQLResolveInfo
|
|
34
37
|
|
|
35
38
|
from infrahub.core.branch import Branch
|
|
36
|
-
from infrahub.core.
|
|
37
|
-
from infrahub.core.relationship.model import RelationshipManager
|
|
39
|
+
from infrahub.core.node import Node
|
|
38
40
|
from infrahub.core.schema.schema_branch import SchemaBranch
|
|
39
41
|
from infrahub.database import InfrahubDatabase
|
|
40
42
|
from infrahub.graphql.types.context import ContextInput
|
|
@@ -143,33 +145,6 @@ class InfrahubMutationMixin:
|
|
|
143
145
|
|
|
144
146
|
return mutation
|
|
145
147
|
|
|
146
|
-
@classmethod
|
|
147
|
-
async def _get_profile_ids(cls, db: InfrahubDatabase, obj: Node) -> set[str]:
|
|
148
|
-
if not hasattr(obj, "profiles"):
|
|
149
|
-
return set()
|
|
150
|
-
profile_rels = await obj.profiles.get_relationships(db=db)
|
|
151
|
-
return {pr.peer_id for pr in profile_rels}
|
|
152
|
-
|
|
153
|
-
@classmethod
|
|
154
|
-
async def _refresh_for_profile_update(
|
|
155
|
-
cls, db: InfrahubDatabase, branch: Branch, obj: Node, previous_profile_ids: set[str] | None = None
|
|
156
|
-
) -> Node:
|
|
157
|
-
if not hasattr(obj, "profiles"):
|
|
158
|
-
return obj
|
|
159
|
-
current_profile_ids = await cls._get_profile_ids(db=db, obj=obj)
|
|
160
|
-
if previous_profile_ids is None or previous_profile_ids != current_profile_ids:
|
|
161
|
-
refreshed_node = await NodeManager.get_one_by_id_or_default_filter(
|
|
162
|
-
db=db,
|
|
163
|
-
kind=cls._meta.active_schema.kind,
|
|
164
|
-
id=obj.get_id(),
|
|
165
|
-
branch=branch,
|
|
166
|
-
include_owner=True,
|
|
167
|
-
include_source=True,
|
|
168
|
-
)
|
|
169
|
-
refreshed_node._node_changelog = obj.node_changelog
|
|
170
|
-
return refreshed_node
|
|
171
|
-
return obj
|
|
172
|
-
|
|
173
148
|
@classmethod
|
|
174
149
|
async def _call_mutate_create_object(cls, data: InputObjectType, db: InfrahubDatabase, branch: Branch) -> Node:
|
|
175
150
|
"""
|
|
@@ -185,100 +160,6 @@ class InfrahubMutationMixin:
|
|
|
185
160
|
|
|
186
161
|
return await cls.mutate_create_object(data=data, db=db, branch=branch)
|
|
187
162
|
|
|
188
|
-
@classmethod
|
|
189
|
-
async def _get_template_relationship_peers(
|
|
190
|
-
cls, db: InfrahubDatabase, template: CoreObjectTemplate, relationship: RelationshipSchema
|
|
191
|
-
) -> Mapping[str, Node]:
|
|
192
|
-
"""For a given relationship on the template, fetch the related peers."""
|
|
193
|
-
template_relationship_manager: RelationshipManager = getattr(template, relationship.name)
|
|
194
|
-
if relationship.cardinality == RelationshipCardinality.MANY:
|
|
195
|
-
return await template_relationship_manager.get_peers(db=db)
|
|
196
|
-
|
|
197
|
-
peers: dict[str, Node] = {}
|
|
198
|
-
template_relationship_peer = await template_relationship_manager.get_peer(db=db)
|
|
199
|
-
if template_relationship_peer:
|
|
200
|
-
peers[template_relationship_peer.id] = template_relationship_peer
|
|
201
|
-
return peers
|
|
202
|
-
|
|
203
|
-
@classmethod
|
|
204
|
-
async def _extract_peer_data(
|
|
205
|
-
cls,
|
|
206
|
-
db: InfrahubDatabase,
|
|
207
|
-
template_peer: Node,
|
|
208
|
-
obj_peer_schema: MainSchemaTypes,
|
|
209
|
-
parent_obj: Node,
|
|
210
|
-
current_template: CoreObjectTemplate,
|
|
211
|
-
) -> Mapping[str, Any]:
|
|
212
|
-
obj_peer_data: dict[str, Any] = {}
|
|
213
|
-
|
|
214
|
-
for attr in template_peer.get_schema().attribute_names:
|
|
215
|
-
if attr not in obj_peer_schema.attribute_names:
|
|
216
|
-
continue
|
|
217
|
-
obj_peer_data[attr] = {"value": getattr(template_peer, attr).value, "source": template_peer.id}
|
|
218
|
-
|
|
219
|
-
for rel in template_peer.get_schema().relationship_names:
|
|
220
|
-
rel_manager: RelationshipManager = getattr(template_peer, rel)
|
|
221
|
-
if (
|
|
222
|
-
rel_manager.schema.kind not in [RelationshipKind.COMPONENT, RelationshipKind.PARENT]
|
|
223
|
-
or rel_manager.schema.name not in obj_peer_schema.relationship_names
|
|
224
|
-
):
|
|
225
|
-
continue
|
|
226
|
-
|
|
227
|
-
if list(await rel_manager.get_peers(db=db)) == [current_template.id]:
|
|
228
|
-
obj_peer_data[rel] = {"id": parent_obj.id}
|
|
229
|
-
|
|
230
|
-
return obj_peer_data
|
|
231
|
-
|
|
232
|
-
@classmethod
|
|
233
|
-
async def _handle_template_relationships(
|
|
234
|
-
cls,
|
|
235
|
-
db: InfrahubDatabase,
|
|
236
|
-
branch: Branch,
|
|
237
|
-
obj: Node,
|
|
238
|
-
template: CoreObjectTemplate,
|
|
239
|
-
data: InputObjectType,
|
|
240
|
-
constraint_runner: NodeConstraintRunner | None = None,
|
|
241
|
-
) -> None:
|
|
242
|
-
if constraint_runner is None:
|
|
243
|
-
component_registry = get_component_registry()
|
|
244
|
-
constraint_runner = await component_registry.get_component(NodeConstraintRunner, db=db, branch=branch)
|
|
245
|
-
|
|
246
|
-
for relationship in obj.get_relationships(kind=RelationshipKind.COMPONENT, exclude=list(data)):
|
|
247
|
-
template_relationship_peers = await cls._get_template_relationship_peers(
|
|
248
|
-
db=db, template=template, relationship=relationship
|
|
249
|
-
)
|
|
250
|
-
if not template_relationship_peers:
|
|
251
|
-
continue
|
|
252
|
-
|
|
253
|
-
for template_relationship_peer in template_relationship_peers.values():
|
|
254
|
-
# We retrieve peer schema for each peer in case we are processing a relationship which is based on a generic
|
|
255
|
-
obj_peer_schema = registry.schema.get_node_schema(
|
|
256
|
-
name=template_relationship_peer.get_schema().kind.removeprefix("Template"),
|
|
257
|
-
branch=branch,
|
|
258
|
-
duplicate=False,
|
|
259
|
-
)
|
|
260
|
-
obj_peer_data = await cls._extract_peer_data(
|
|
261
|
-
db=db,
|
|
262
|
-
template_peer=template_relationship_peer,
|
|
263
|
-
obj_peer_schema=obj_peer_schema,
|
|
264
|
-
parent_obj=obj,
|
|
265
|
-
current_template=template,
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
obj_peer = await Node.init(schema=obj_peer_schema, db=db, branch=branch)
|
|
269
|
-
await obj_peer.new(db=db, **obj_peer_data)
|
|
270
|
-
await constraint_runner.check(node=obj_peer, field_filters=list(obj_peer_data))
|
|
271
|
-
await obj_peer.save(db=db)
|
|
272
|
-
|
|
273
|
-
await cls._handle_template_relationships(
|
|
274
|
-
db=db,
|
|
275
|
-
branch=branch,
|
|
276
|
-
constraint_runner=constraint_runner,
|
|
277
|
-
obj=obj_peer,
|
|
278
|
-
template=template_relationship_peer,
|
|
279
|
-
data=data,
|
|
280
|
-
)
|
|
281
|
-
|
|
282
163
|
@classmethod
|
|
283
164
|
async def mutate_create(
|
|
284
165
|
cls,
|
|
@@ -301,51 +182,15 @@ class InfrahubMutationMixin:
|
|
|
301
182
|
db: InfrahubDatabase,
|
|
302
183
|
branch: Branch,
|
|
303
184
|
) -> Node:
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
185
|
+
schema = cls._meta.active_schema
|
|
186
|
+
if isinstance(schema, GenericSchema):
|
|
187
|
+
raise ValueError(f"Node of generic schema `{schema.name=}` can not be instantiated.")
|
|
188
|
+
return await create_node(
|
|
189
|
+
data=dict(data),
|
|
190
|
+
db=db,
|
|
191
|
+
branch=branch,
|
|
192
|
+
schema=schema,
|
|
307
193
|
)
|
|
308
|
-
node_class = Node
|
|
309
|
-
if cls._meta.active_schema.kind in registry.node:
|
|
310
|
-
node_class = registry.node[cls._meta.active_schema.kind]
|
|
311
|
-
|
|
312
|
-
fields_to_validate = list(data)
|
|
313
|
-
if db.is_transaction:
|
|
314
|
-
obj = await node_class.init(db=db, schema=cls._meta.schema, branch=branch)
|
|
315
|
-
await obj.new(db=db, **data)
|
|
316
|
-
await node_constraint_runner.check(node=obj, field_filters=fields_to_validate)
|
|
317
|
-
await obj.save(db=db)
|
|
318
|
-
|
|
319
|
-
object_template = await obj.get_object_template(db=db)
|
|
320
|
-
if object_template:
|
|
321
|
-
await cls._handle_template_relationships(
|
|
322
|
-
db=db,
|
|
323
|
-
branch=branch,
|
|
324
|
-
template=object_template,
|
|
325
|
-
obj=obj,
|
|
326
|
-
data=data,
|
|
327
|
-
)
|
|
328
|
-
else:
|
|
329
|
-
async with db.start_transaction() as dbt:
|
|
330
|
-
obj = await node_class.init(db=dbt, schema=cls._meta.schema, branch=branch)
|
|
331
|
-
await obj.new(db=dbt, **data)
|
|
332
|
-
await node_constraint_runner.check(node=obj, field_filters=fields_to_validate)
|
|
333
|
-
await obj.save(db=dbt)
|
|
334
|
-
|
|
335
|
-
object_template = await obj.get_object_template(db=dbt)
|
|
336
|
-
if object_template:
|
|
337
|
-
await cls._handle_template_relationships(
|
|
338
|
-
db=dbt,
|
|
339
|
-
branch=branch,
|
|
340
|
-
template=object_template,
|
|
341
|
-
obj=obj,
|
|
342
|
-
data=data,
|
|
343
|
-
)
|
|
344
|
-
|
|
345
|
-
if await cls._get_profile_ids(db=db, obj=obj):
|
|
346
|
-
obj = await cls._refresh_for_profile_update(db=db, branch=branch, obj=obj)
|
|
347
|
-
|
|
348
|
-
return obj
|
|
349
194
|
|
|
350
195
|
@classmethod
|
|
351
196
|
async def mutate_create_to_graphql(cls, info: GraphQLResolveInfo, db: InfrahubDatabase, obj: Node) -> Self:
|
|
@@ -439,7 +284,7 @@ class InfrahubMutationMixin:
|
|
|
439
284
|
component_registry = get_component_registry()
|
|
440
285
|
node_constraint_runner = await component_registry.get_component(NodeConstraintRunner, db=db, branch=branch)
|
|
441
286
|
|
|
442
|
-
before_mutate_profile_ids = await
|
|
287
|
+
before_mutate_profile_ids = await get_profile_ids(db=db, obj=obj)
|
|
443
288
|
await obj.from_graphql(db=db, data=data)
|
|
444
289
|
fields_to_validate = list(data)
|
|
445
290
|
await node_constraint_runner.check(
|
|
@@ -453,8 +298,12 @@ class InfrahubMutationMixin:
|
|
|
453
298
|
|
|
454
299
|
await obj.save(db=db, fields=fields)
|
|
455
300
|
|
|
456
|
-
obj = await
|
|
457
|
-
db=db,
|
|
301
|
+
obj = await refresh_for_profile_update(
|
|
302
|
+
db=db,
|
|
303
|
+
branch=branch,
|
|
304
|
+
obj=obj,
|
|
305
|
+
previous_profile_ids=before_mutate_profile_ids,
|
|
306
|
+
schema=cls._meta.active_schema,
|
|
458
307
|
)
|
|
459
308
|
return obj
|
|
460
309
|
|
|
@@ -18,10 +18,10 @@ from infrahub.database import InfrahubDatabase, retry_db_transaction
|
|
|
18
18
|
from infrahub.exceptions import BranchNotFoundError, PermissionDeniedError, ValidationError
|
|
19
19
|
from infrahub.graphql.mutations.main import InfrahubMutationMixin
|
|
20
20
|
from infrahub.graphql.types.enums import CheckType as GraphQLCheckType
|
|
21
|
-
from infrahub.message_bus import messages
|
|
22
21
|
from infrahub.proposed_change.constants import ProposedChangeState
|
|
23
|
-
from infrahub.workflows.catalogue import PROPOSED_CHANGE_MERGE
|
|
22
|
+
from infrahub.workflows.catalogue import PROPOSED_CHANGE_MERGE, REQUEST_PROPOSED_CHANGE_PIPELINE
|
|
24
23
|
|
|
24
|
+
from ...proposed_change.models import RequestProposedChangePipeline
|
|
25
25
|
from ..types.task import TaskInfo
|
|
26
26
|
from .main import InfrahubMutationOptions
|
|
27
27
|
|
|
@@ -65,18 +65,18 @@ class InfrahubProposedChangeMutation(InfrahubMutationMixin, Mutation):
|
|
|
65
65
|
)
|
|
66
66
|
|
|
67
67
|
if graphql_context.service:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
68
|
+
request_proposed_change_model = RequestProposedChangePipeline(
|
|
69
|
+
proposed_change=proposed_change.id,
|
|
70
|
+
source_branch=source_branch.name,
|
|
71
|
+
source_branch_sync_with_git=source_branch.sync_with_git,
|
|
72
|
+
destination_branch=destination_branch,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
await graphql_context.service.workflow.submit_workflow(
|
|
76
|
+
workflow=REQUEST_PROPOSED_CHANGE_PIPELINE,
|
|
77
|
+
parameters={"model": request_proposed_change_model},
|
|
78
|
+
context=graphql_context.get_context(),
|
|
79
|
+
)
|
|
80
80
|
|
|
81
81
|
return proposed_change, result
|
|
82
82
|
|
|
@@ -175,16 +175,19 @@ class ProposedChangeRequestRunCheck(Mutation):
|
|
|
175
175
|
destination_branch = proposed_change.destination_branch.value
|
|
176
176
|
source_branch = await _get_source_branch(db=graphql_context.db, name=proposed_change.source_branch.value)
|
|
177
177
|
|
|
178
|
-
|
|
178
|
+
request_proposed_change_model = RequestProposedChangePipeline(
|
|
179
179
|
proposed_change=proposed_change.id,
|
|
180
180
|
source_branch=source_branch.name,
|
|
181
181
|
source_branch_sync_with_git=source_branch.sync_with_git,
|
|
182
182
|
destination_branch=destination_branch,
|
|
183
183
|
check_type=check_type,
|
|
184
|
-
context=graphql_context.get_context(),
|
|
185
184
|
)
|
|
186
185
|
if graphql_context.service:
|
|
187
|
-
await graphql_context.service.
|
|
186
|
+
await graphql_context.service.workflow.submit_workflow(
|
|
187
|
+
workflow=REQUEST_PROPOSED_CHANGE_PIPELINE,
|
|
188
|
+
parameters={"model": request_proposed_change_model},
|
|
189
|
+
context=graphql_context.get_context(),
|
|
190
|
+
)
|
|
188
191
|
|
|
189
192
|
return {"ok": True}
|
|
190
193
|
|
|
@@ -85,6 +85,7 @@ class RelationshipAdd(Mutation):
|
|
|
85
85
|
nodes = await _validate_peers(info=info, data=data)
|
|
86
86
|
await _validate_permissions(info=info, source_node=source, peers=nodes)
|
|
87
87
|
await _validate_peer_types(info=info, data=data, source_node=source, peers=nodes)
|
|
88
|
+
await _validate_peer_parents(info=info, data=data, source_node=source, peers=nodes)
|
|
88
89
|
|
|
89
90
|
# This has to be done after validating the permissions
|
|
90
91
|
await apply_external_context(graphql_context=graphql_context, context_input=context)
|
|
@@ -406,6 +407,37 @@ async def _validate_peer_types(
|
|
|
406
407
|
)
|
|
407
408
|
|
|
408
409
|
|
|
410
|
+
async def _validate_peer_parents(
|
|
411
|
+
info: GraphQLResolveInfo, data: RelationshipNodesInput, source_node: Node, peers: dict[str, Node]
|
|
412
|
+
) -> None:
|
|
413
|
+
relationship_name = str(data.name)
|
|
414
|
+
rel_schema = source_node.get_schema().get_relationship(name=relationship_name)
|
|
415
|
+
if not rel_schema.common_parent:
|
|
416
|
+
return
|
|
417
|
+
|
|
418
|
+
graphql_context: GraphqlContext = info.context
|
|
419
|
+
|
|
420
|
+
source_node_parent = await source_node.get_parent_relationship_peer(
|
|
421
|
+
db=graphql_context.db, name=rel_schema.common_parent
|
|
422
|
+
)
|
|
423
|
+
if not source_node_parent:
|
|
424
|
+
# If the schema is properly validated we are not expecting this to happen
|
|
425
|
+
raise ValidationError(f"Node {source_node.id} ({source_node.get_kind()!r}) does not have a parent peer")
|
|
426
|
+
|
|
427
|
+
parents: set[str] = {source_node_parent.id}
|
|
428
|
+
for peer in peers.values():
|
|
429
|
+
peer_parent = await peer.get_parent_relationship_peer(db=graphql_context.db, name=rel_schema.common_parent)
|
|
430
|
+
if not peer_parent:
|
|
431
|
+
# If the schema is properly validated we are not expecting this to happen
|
|
432
|
+
raise ValidationError(f"Peer {peer.id} ({peer.get_kind()!r}) does not have a parent peer")
|
|
433
|
+
parents.add(peer_parent.id)
|
|
434
|
+
|
|
435
|
+
if len(parents) > 1:
|
|
436
|
+
raise ValidationError(
|
|
437
|
+
f"Cannot relate {source_node.id!r} to '{relationship_name}' peers that do not have the same parent"
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
|
|
409
441
|
async def _collect_current_peers(
|
|
410
442
|
info: GraphQLResolveInfo, data: RelationshipNodesInput, source_node: Node
|
|
411
443
|
) -> dict[str, RelationshipPeerData]:
|
|
@@ -6,15 +6,18 @@ from graphene import Boolean, Field, InputField, InputObjectType, Int, List, Mut
|
|
|
6
6
|
from graphene.types.generic import GenericScalar
|
|
7
7
|
from typing_extensions import Self
|
|
8
8
|
|
|
9
|
-
from infrahub.core import registry
|
|
10
|
-
from infrahub.core.constants import InfrahubKind
|
|
9
|
+
from infrahub.core import protocols, registry
|
|
10
|
+
from infrahub.core.constants import InfrahubKind, NumberPoolType
|
|
11
11
|
from infrahub.core.ipam.constants import PrefixMemberType
|
|
12
|
+
from infrahub.core.manager import NodeManager
|
|
12
13
|
from infrahub.core.schema import NodeSchema
|
|
14
|
+
from infrahub.core.schema.attribute_parameters import NumberAttributeParameters
|
|
13
15
|
from infrahub.database import retry_db_transaction
|
|
14
16
|
from infrahub.exceptions import QueryValidationError, SchemaNotFoundError, ValidationError
|
|
17
|
+
from infrahub.pools.registration import get_branches_with_schema_number_pool
|
|
15
18
|
|
|
16
19
|
from ..queries.resource_manager import PoolAllocatedNode
|
|
17
|
-
from .main import InfrahubMutationMixin, InfrahubMutationOptions
|
|
20
|
+
from .main import DeleteResult, InfrahubMutationMixin, InfrahubMutationOptions
|
|
18
21
|
|
|
19
22
|
if TYPE_CHECKING:
|
|
20
23
|
from graphql import GraphQLResolveInfo
|
|
@@ -177,14 +180,16 @@ class InfrahubNumberPoolMutation(InfrahubMutationMixin, Mutation):
|
|
|
177
180
|
database: InfrahubDatabase | None = None, # noqa: ARG003
|
|
178
181
|
) -> Any:
|
|
179
182
|
try:
|
|
180
|
-
|
|
181
|
-
if not
|
|
183
|
+
schema_node = registry.schema.get(name=data["node"].value)
|
|
184
|
+
if not schema_node.is_generic_schema and not schema_node.is_node_schema:
|
|
182
185
|
raise ValidationError(input_value="The selected model is not a Node or a Generic")
|
|
183
186
|
except SchemaNotFoundError as exc:
|
|
184
187
|
exc.message = "The selected model does not exist"
|
|
185
188
|
raise exc
|
|
186
189
|
|
|
187
|
-
attributes = [
|
|
190
|
+
attributes = [
|
|
191
|
+
attribute for attribute in schema_node.attributes if attribute.name == data["node_attribute"].value
|
|
192
|
+
]
|
|
188
193
|
if not attributes:
|
|
189
194
|
raise ValidationError(input_value="The selected attribute doesn't exist in the selected model")
|
|
190
195
|
|
|
@@ -192,9 +197,22 @@ class InfrahubNumberPoolMutation(InfrahubMutationMixin, Mutation):
|
|
|
192
197
|
if attribute.kind != "Number":
|
|
193
198
|
raise ValidationError(input_value="The selected attribute is not of the kind Number")
|
|
194
199
|
|
|
195
|
-
|
|
200
|
+
start_range = data["start_range"].value
|
|
201
|
+
end_range = data["end_range"].value
|
|
202
|
+
if start_range > end_range:
|
|
196
203
|
raise ValidationError(input_value="start_range can't be larger than end_range")
|
|
197
204
|
|
|
205
|
+
if not isinstance(attribute.parameters, NumberAttributeParameters):
|
|
206
|
+
raise ValidationError(
|
|
207
|
+
input_value="The selected attribute parameters are not of the kind NumberAttributeParameters"
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
if attribute.parameters.min_value is not None and start_range < attribute.parameters.min_value:
|
|
211
|
+
raise ValidationError(input_value="start_range can't be less than min_value")
|
|
212
|
+
|
|
213
|
+
if attribute.parameters.max_value is not None and end_range > attribute.parameters.max_value:
|
|
214
|
+
raise ValidationError(input_value="end_range can't be larger than max_value")
|
|
215
|
+
|
|
198
216
|
return await super().mutate_create(info=info, data=data, branch=branch)
|
|
199
217
|
|
|
200
218
|
@classmethod
|
|
@@ -217,7 +235,45 @@ class InfrahubNumberPoolMutation(InfrahubMutationMixin, Mutation):
|
|
|
217
235
|
number_pool, result = await super().mutate_update(
|
|
218
236
|
info=info, data=data, branch=branch, database=dbt, node=node
|
|
219
237
|
)
|
|
238
|
+
|
|
239
|
+
if number_pool.pool_type.value.value == NumberPoolType.SCHEMA.value and ( # type: ignore[attr-defined]
|
|
240
|
+
"start_range" in data.keys() or "end_range" in data.keys()
|
|
241
|
+
):
|
|
242
|
+
raise ValidationError(
|
|
243
|
+
input_value="start_range or end_range can't be updated on schema defined pools, update the schema in the default branch instead"
|
|
244
|
+
)
|
|
245
|
+
|
|
220
246
|
if number_pool.start_range.value > number_pool.end_range.value: # type: ignore[attr-defined]
|
|
221
247
|
raise ValidationError(input_value="start_range can't be larger than end_range")
|
|
222
248
|
|
|
223
249
|
return number_pool, result
|
|
250
|
+
|
|
251
|
+
@classmethod
|
|
252
|
+
@retry_db_transaction(name="resource_manager_update")
|
|
253
|
+
async def mutate_delete(
|
|
254
|
+
cls,
|
|
255
|
+
info: GraphQLResolveInfo,
|
|
256
|
+
data: InputObjectType,
|
|
257
|
+
branch: Branch,
|
|
258
|
+
) -> DeleteResult:
|
|
259
|
+
graphql_context: GraphqlContext = info.context
|
|
260
|
+
|
|
261
|
+
number_pool = await NodeManager.find_object(
|
|
262
|
+
db=graphql_context.db,
|
|
263
|
+
kind=protocols.CoreNumberPool,
|
|
264
|
+
id=data.get("id"),
|
|
265
|
+
hfid=data.get("hfid"),
|
|
266
|
+
branch=branch,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
violating_branches = get_branches_with_schema_number_pool(
|
|
270
|
+
kind=number_pool.node.value, attribute_name=number_pool.node_attribute.value
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
if violating_branches:
|
|
274
|
+
raise ValidationError(
|
|
275
|
+
input_value=f"Unable to delete number pool {number_pool.node.value}.{number_pool.node_attribute.value}"
|
|
276
|
+
f" is in use (branches: {','.join(violating_branches)})"
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
return await super().mutate_delete(info=info, data=data, branch=branch)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from graphene import Field, ObjectType, String
|
|
2
|
+
from graphene.types.generic import GenericScalar
|
|
3
|
+
from graphql import GraphQLResolveInfo
|
|
4
|
+
|
|
5
|
+
from infrahub.core import registry
|
|
6
|
+
from infrahub.core.convert_object_type.schema_mapping import get_schema_mapping
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FieldsMapping(ObjectType):
|
|
10
|
+
mapping = GenericScalar(required=True)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
async def fields_mapping_type_conversion_resolver(
|
|
14
|
+
root: dict, # noqa: ARG001
|
|
15
|
+
info: GraphQLResolveInfo,
|
|
16
|
+
source_kind: str,
|
|
17
|
+
target_kind: str,
|
|
18
|
+
) -> dict:
|
|
19
|
+
source_schema = registry.get_node_schema(name=source_kind, branch=info.context.branch)
|
|
20
|
+
target_schema = registry.get_node_schema(name=target_kind, branch=info.context.branch)
|
|
21
|
+
|
|
22
|
+
mapping = get_schema_mapping(source_schema=source_schema, target_schema=target_schema)
|
|
23
|
+
mapping_dict = {field_name: model.model_dump(mode="json") for field_name, model in mapping.items()}
|
|
24
|
+
return {"mapping": mapping_dict}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
FieldsMappingTypeConversion = Field(
|
|
28
|
+
FieldsMapping,
|
|
29
|
+
source_kind=String(),
|
|
30
|
+
target_kind=String(),
|
|
31
|
+
description="Retrieve fields mapping for converting object type",
|
|
32
|
+
resolver=fields_mapping_type_conversion_resolver,
|
|
33
|
+
required=True,
|
|
34
|
+
)
|
|
@@ -306,7 +306,13 @@ async def resolve_number_pool_allocation(
|
|
|
306
306
|
async def resolve_number_pool_utilization(
|
|
307
307
|
db: InfrahubDatabase, pool: CoreNode, at: Timestamp | str | None, branch: Branch
|
|
308
308
|
) -> dict:
|
|
309
|
-
|
|
309
|
+
"""
|
|
310
|
+
Returns a mapping containg utilization info of a number pool.
|
|
311
|
+
The utilization is calculated as the percentage of the total number of values in the pool that are not excluded for the corresponding attribute.
|
|
312
|
+
"""
|
|
313
|
+
|
|
314
|
+
core_number_pool = await registry.manager.get_one_by_id_or_default_filter(db=db, id=pool.id, kind="CoreNumberPool")
|
|
315
|
+
number_pool = NumberUtilizationGetter(db=db, pool=core_number_pool, at=at, branch=branch)
|
|
310
316
|
await number_pool.load_data()
|
|
311
317
|
|
|
312
318
|
return {
|
|
@@ -99,7 +99,7 @@ class ManyRelationshipResolver:
|
|
|
99
99
|
filters = {
|
|
100
100
|
f"{info.field_name}__{key}": value
|
|
101
101
|
for key, value in kwargs.items()
|
|
102
|
-
if "__" in key and value or key in ["id", "ids"]
|
|
102
|
+
if ("__" in key and value) or key in ["id", "ids"]
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
response: dict[str, Any] = {"edges": [], "count": None}
|
|
@@ -99,7 +99,7 @@ async def default_resolver(*args: Any, **kwargs) -> dict | list[dict] | None:
|
|
|
99
99
|
filters = {
|
|
100
100
|
f"{info.field_name}__{key}": value
|
|
101
101
|
for key, value in kwargs.items()
|
|
102
|
-
if "__" in key and value or key in ["id", "ids"]
|
|
102
|
+
if ("__" in key and value) or key in ["id", "ids"]
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
async with graphql_context.db.start_session(read_only=True) as db:
|
|
@@ -288,7 +288,7 @@ async def hierarchy_resolver(
|
|
|
288
288
|
filters = {
|
|
289
289
|
f"{info.field_name}__{key}": value
|
|
290
290
|
for key, value in kwargs.items()
|
|
291
|
-
if "__" in key and value or key in ["id", "ids"]
|
|
291
|
+
if ("__" in key and value) or key in ["id", "ids"]
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
response: dict[str, Any] = {"edges": [], "count": None}
|
|
@@ -107,7 +107,7 @@ class SingleRelationshipResolver:
|
|
|
107
107
|
filters = {
|
|
108
108
|
f"{field_name}__{key}": value
|
|
109
109
|
for key, value in kwargs.items()
|
|
110
|
-
if "__" in key and value or key in ["id", "ids"]
|
|
110
|
+
if ("__" in key and value) or key in ["id", "ids"]
|
|
111
111
|
}
|
|
112
112
|
async with db.start_session(read_only=True) as dbs:
|
|
113
113
|
objs = await NodeManager.query_peers(
|
infrahub/graphql/schema.py
CHANGED
|
@@ -16,6 +16,7 @@ from .mutations.branch import (
|
|
|
16
16
|
BranchValidate,
|
|
17
17
|
)
|
|
18
18
|
from .mutations.computed_attribute import UpdateComputedAttribute
|
|
19
|
+
from .mutations.convert_object_type import ConvertObjectType
|
|
19
20
|
from .mutations.diff import DiffUpdateMutation
|
|
20
21
|
from .mutations.diff_conflict import ResolveDiffConflict
|
|
21
22
|
from .mutations.generator import GeneratorDefinitionRequestRun
|
|
@@ -48,6 +49,7 @@ from .queries import (
|
|
|
48
49
|
InfrahubStatus,
|
|
49
50
|
Relationship,
|
|
50
51
|
)
|
|
52
|
+
from .queries.convert_object_type_mapping import FieldsMappingTypeConversion
|
|
51
53
|
from .queries.diff.tree import DiffTreeQuery, DiffTreeSummaryQuery
|
|
52
54
|
from .queries.event import Event
|
|
53
55
|
from .queries.task import Task, TaskBranchStatus
|
|
@@ -77,6 +79,8 @@ class InfrahubBaseQuery(ObjectType):
|
|
|
77
79
|
InfrahubResourcePoolAllocated = InfrahubResourcePoolAllocated
|
|
78
80
|
InfrahubResourcePoolUtilization = InfrahubResourcePoolUtilization
|
|
79
81
|
|
|
82
|
+
FieldsMappingTypeConversion = FieldsMappingTypeConversion
|
|
83
|
+
|
|
80
84
|
|
|
81
85
|
class InfrahubBaseMutation(ObjectType):
|
|
82
86
|
InfrahubAccountTokenCreate = InfrahubAccountTokenCreate.Field()
|
|
@@ -109,3 +113,5 @@ class InfrahubBaseMutation(ObjectType):
|
|
|
109
113
|
SchemaEnumAdd = SchemaEnumAdd.Field()
|
|
110
114
|
SchemaEnumRemove = SchemaEnumRemove.Field()
|
|
111
115
|
ResolveDiffConflict = ResolveDiffConflict.Field()
|
|
116
|
+
|
|
117
|
+
ConvertObjectType = ConvertObjectType.Field()
|
infrahub/menu/menu.py
CHANGED
|
@@ -57,7 +57,7 @@ default_menu = [
|
|
|
57
57
|
name="IPPrefix",
|
|
58
58
|
label="IP Prefixes",
|
|
59
59
|
kind=InfrahubKind.IPPREFIX,
|
|
60
|
-
path="/ipam
|
|
60
|
+
path="/ipam",
|
|
61
61
|
icon=_extract_node_icon(infrahub_schema.get(InfrahubKind.IPPREFIX)),
|
|
62
62
|
protected=True,
|
|
63
63
|
section=MenuSection.INTERNAL,
|
|
@@ -68,7 +68,7 @@ default_menu = [
|
|
|
68
68
|
name="IPAddress",
|
|
69
69
|
label="IP Addresses",
|
|
70
70
|
kind=InfrahubKind.IPPREFIX,
|
|
71
|
-
path="/ipam/
|
|
71
|
+
path="/ipam/ip_addresses",
|
|
72
72
|
icon=_extract_node_icon(infrahub_schema.get(InfrahubKind.IPADDRESS)),
|
|
73
73
|
protected=True,
|
|
74
74
|
section=MenuSection.INTERNAL,
|
|
@@ -79,6 +79,7 @@ default_menu = [
|
|
|
79
79
|
name="Namespaces",
|
|
80
80
|
label="Namespaces",
|
|
81
81
|
kind=InfrahubKind.IPNAMESPACE,
|
|
82
|
+
path="/ipam/namespaces",
|
|
82
83
|
icon=_extract_node_icon(infrahub_schema.get(InfrahubKind.IPNAMESPACE)),
|
|
83
84
|
protected=True,
|
|
84
85
|
section=MenuSection.INTERNAL,
|
|
@@ -246,6 +247,37 @@ default_menu = [
|
|
|
246
247
|
section=MenuSection.INTERNAL,
|
|
247
248
|
order_weight=2000,
|
|
248
249
|
),
|
|
250
|
+
MenuItemDefinition(
|
|
251
|
+
namespace="Builtin",
|
|
252
|
+
name="TriggerDefinition",
|
|
253
|
+
label="Events",
|
|
254
|
+
icon=_extract_node_icon(infrahub_schema.get(InfrahubKind.TRIGGERRULE)),
|
|
255
|
+
protected=True,
|
|
256
|
+
section=MenuSection.INTERNAL,
|
|
257
|
+
order_weight=6000,
|
|
258
|
+
children=[
|
|
259
|
+
MenuItemDefinition(
|
|
260
|
+
namespace="Builtin",
|
|
261
|
+
name="TriggerRule",
|
|
262
|
+
label="Rules",
|
|
263
|
+
kind=InfrahubKind.TRIGGERRULE,
|
|
264
|
+
icon=_extract_node_icon(infrahub_schema.get(InfrahubKind.TRIGGERRULE)),
|
|
265
|
+
protected=True,
|
|
266
|
+
section=MenuSection.INTERNAL,
|
|
267
|
+
order_weight=1000,
|
|
268
|
+
),
|
|
269
|
+
MenuItemDefinition(
|
|
270
|
+
namespace="Builtin",
|
|
271
|
+
name="Action",
|
|
272
|
+
label="Actions",
|
|
273
|
+
kind=InfrahubKind.ACTION,
|
|
274
|
+
icon=_extract_node_icon(infrahub_schema.get(InfrahubKind.ACTION)),
|
|
275
|
+
protected=True,
|
|
276
|
+
section=MenuSection.INTERNAL,
|
|
277
|
+
order_weight=2000,
|
|
278
|
+
),
|
|
279
|
+
],
|
|
280
|
+
),
|
|
249
281
|
],
|
|
250
282
|
),
|
|
251
283
|
MenuItemDefinition(
|