infrahub-server 1.2.0b1__py3-none-any.whl → 1.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- infrahub/api/dependencies.py +6 -6
- infrahub/api/diff/validation_models.py +7 -7
- infrahub/api/schema.py +1 -1
- infrahub/artifacts/models.py +1 -3
- infrahub/artifacts/tasks.py +1 -3
- infrahub/cli/__init__.py +13 -9
- infrahub/cli/constants.py +3 -0
- infrahub/cli/db.py +165 -183
- infrahub/cli/upgrade.py +146 -0
- infrahub/computed_attribute/gather.py +185 -0
- infrahub/computed_attribute/models.py +239 -11
- infrahub/computed_attribute/tasks.py +77 -442
- infrahub/computed_attribute/triggers.py +11 -45
- infrahub/config.py +43 -32
- infrahub/context.py +14 -0
- infrahub/core/account.py +4 -4
- infrahub/core/attribute.py +57 -57
- infrahub/core/branch/tasks.py +12 -9
- infrahub/core/changelog/diff.py +16 -8
- infrahub/core/changelog/models.py +189 -26
- infrahub/core/constants/__init__.py +5 -1
- infrahub/core/constants/infrahubkind.py +2 -0
- infrahub/core/constraint/node/runner.py +9 -8
- infrahub/core/diff/branch_differ.py +10 -10
- infrahub/core/diff/ipam_diff_parser.py +4 -5
- infrahub/core/diff/model/diff.py +27 -27
- infrahub/core/diff/model/path.py +3 -3
- infrahub/core/diff/query/merge.py +20 -17
- infrahub/core/diff/query_parser.py +4 -4
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/initialization.py +1 -10
- infrahub/core/ipam/constants.py +3 -4
- infrahub/core/ipam/reconciler.py +12 -12
- infrahub/core/ipam/utilization.py +10 -13
- infrahub/core/manager.py +34 -34
- infrahub/core/merge.py +7 -7
- infrahub/core/migrations/__init__.py +2 -3
- infrahub/core/migrations/graph/__init__.py +9 -4
- infrahub/core/migrations/graph/m017_add_core_profile.py +1 -5
- infrahub/core/migrations/graph/m018_uniqueness_nulls.py +4 -4
- infrahub/core/migrations/graph/m020_duplicate_edges.py +160 -0
- infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +51 -0
- infrahub/core/migrations/graph/{m020_add_generate_template_attr.py → m022_add_generate_template_attr.py} +3 -3
- infrahub/core/migrations/graph/m023_deduplicate_cardinality_one_relationships.py +96 -0
- infrahub/core/migrations/query/attribute_add.py +2 -2
- infrahub/core/migrations/query/node_duplicate.py +18 -21
- infrahub/core/migrations/query/schema_attribute_update.py +2 -2
- infrahub/core/migrations/schema/models.py +19 -4
- infrahub/core/migrations/schema/tasks.py +2 -2
- infrahub/core/migrations/shared.py +16 -16
- infrahub/core/models.py +15 -6
- infrahub/core/node/__init__.py +29 -28
- infrahub/core/node/base.py +2 -4
- infrahub/core/node/constraints/attribute_uniqueness.py +2 -2
- infrahub/core/node/constraints/grouped_uniqueness.py +99 -47
- infrahub/core/node/constraints/interface.py +1 -2
- infrahub/core/node/delete_validator.py +3 -5
- infrahub/core/node/ipam.py +4 -4
- infrahub/core/node/permissions.py +7 -7
- infrahub/core/node/resource_manager/ip_address_pool.py +6 -6
- infrahub/core/node/resource_manager/ip_prefix_pool.py +6 -6
- infrahub/core/node/resource_manager/number_pool.py +3 -3
- infrahub/core/path.py +12 -12
- infrahub/core/property.py +11 -11
- infrahub/core/protocols.py +5 -0
- infrahub/core/protocols_base.py +21 -21
- infrahub/core/query/__init__.py +33 -33
- infrahub/core/query/attribute.py +6 -4
- infrahub/core/query/diff.py +3 -3
- infrahub/core/query/node.py +82 -32
- infrahub/core/query/relationship.py +24 -24
- infrahub/core/query/resource_manager.py +2 -0
- infrahub/core/query/standard_node.py +3 -3
- infrahub/core/query/subquery.py +9 -9
- infrahub/core/registry.py +13 -15
- infrahub/core/relationship/constraints/count.py +3 -4
- infrahub/core/relationship/constraints/peer_kind.py +3 -4
- infrahub/core/relationship/constraints/profiles_kind.py +2 -2
- infrahub/core/relationship/model.py +40 -46
- infrahub/core/schema/attribute_schema.py +9 -9
- infrahub/core/schema/basenode_schema.py +93 -44
- infrahub/core/schema/computed_attribute.py +3 -3
- infrahub/core/schema/definitions/core/__init__.py +13 -19
- infrahub/core/schema/definitions/core/account.py +151 -148
- infrahub/core/schema/definitions/core/artifact.py +122 -113
- infrahub/core/schema/definitions/core/builtin.py +19 -16
- infrahub/core/schema/definitions/core/check.py +61 -53
- infrahub/core/schema/definitions/core/core.py +17 -0
- infrahub/core/schema/definitions/core/generator.py +89 -85
- infrahub/core/schema/definitions/core/graphql_query.py +72 -70
- infrahub/core/schema/definitions/core/group.py +96 -93
- infrahub/core/schema/definitions/core/ipam.py +176 -235
- infrahub/core/schema/definitions/core/lineage.py +18 -16
- infrahub/core/schema/definitions/core/menu.py +42 -40
- infrahub/core/schema/definitions/core/permission.py +144 -142
- infrahub/core/schema/definitions/core/profile.py +16 -27
- infrahub/core/schema/definitions/core/propose_change.py +88 -79
- infrahub/core/schema/definitions/core/propose_change_comment.py +170 -165
- infrahub/core/schema/definitions/core/propose_change_validator.py +290 -288
- infrahub/core/schema/definitions/core/repository.py +231 -225
- infrahub/core/schema/definitions/core/resource_pool.py +156 -166
- infrahub/core/schema/definitions/core/template.py +27 -12
- infrahub/core/schema/definitions/core/transform.py +85 -76
- infrahub/core/schema/definitions/core/webhook.py +127 -101
- infrahub/core/schema/definitions/internal.py +16 -16
- infrahub/core/schema/dropdown.py +3 -4
- infrahub/core/schema/generated/attribute_schema.py +15 -18
- infrahub/core/schema/generated/base_node_schema.py +12 -14
- infrahub/core/schema/generated/node_schema.py +3 -5
- infrahub/core/schema/generated/relationship_schema.py +9 -11
- infrahub/core/schema/generic_schema.py +2 -2
- infrahub/core/schema/manager.py +20 -9
- infrahub/core/schema/node_schema.py +4 -2
- infrahub/core/schema/relationship_schema.py +7 -7
- infrahub/core/schema/schema_branch.py +276 -138
- infrahub/core/schema/schema_branch_computed.py +41 -4
- infrahub/core/task/task.py +3 -3
- infrahub/core/task/user_task.py +15 -15
- infrahub/core/utils.py +20 -18
- infrahub/core/validators/__init__.py +1 -3
- infrahub/core/validators/aggregated_checker.py +2 -2
- infrahub/core/validators/attribute/choices.py +2 -2
- infrahub/core/validators/attribute/enum.py +2 -2
- infrahub/core/validators/attribute/kind.py +2 -2
- infrahub/core/validators/attribute/length.py +2 -2
- infrahub/core/validators/attribute/optional.py +2 -2
- infrahub/core/validators/attribute/regex.py +2 -2
- infrahub/core/validators/attribute/unique.py +2 -2
- infrahub/core/validators/checks_runner.py +25 -2
- infrahub/core/validators/determiner.py +1 -3
- infrahub/core/validators/interface.py +6 -2
- infrahub/core/validators/model.py +22 -3
- infrahub/core/validators/models/validate_migration.py +17 -4
- infrahub/core/validators/node/attribute.py +2 -2
- infrahub/core/validators/node/generate_profile.py +2 -2
- infrahub/core/validators/node/hierarchy.py +3 -5
- infrahub/core/validators/node/inherit_from.py +27 -5
- infrahub/core/validators/node/relationship.py +2 -2
- infrahub/core/validators/relationship/count.py +4 -4
- infrahub/core/validators/relationship/optional.py +2 -2
- infrahub/core/validators/relationship/peer.py +2 -2
- infrahub/core/validators/shared.py +2 -2
- infrahub/core/validators/tasks.py +8 -0
- infrahub/core/validators/uniqueness/checker.py +22 -21
- infrahub/core/validators/uniqueness/index.py +2 -2
- infrahub/core/validators/uniqueness/model.py +11 -11
- infrahub/database/__init__.py +26 -22
- infrahub/database/metrics.py +7 -1
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +1 -3
- infrahub/dependencies/component/registry.py +2 -2
- infrahub/events/__init__.py +25 -2
- infrahub/events/artifact_action.py +13 -25
- infrahub/events/branch_action.py +26 -18
- infrahub/events/generator.py +71 -0
- infrahub/events/group_action.py +10 -24
- infrahub/events/models.py +10 -16
- infrahub/events/node_action.py +87 -32
- infrahub/events/repository_action.py +5 -18
- infrahub/events/schema_action.py +4 -9
- infrahub/events/utils.py +16 -0
- infrahub/events/validator_action.py +55 -0
- infrahub/exceptions.py +23 -24
- infrahub/generators/models.py +1 -3
- infrahub/git/base.py +7 -7
- infrahub/git/integrator.py +26 -25
- infrahub/git/models.py +22 -9
- infrahub/git/repository.py +3 -3
- infrahub/git/tasks.py +67 -49
- infrahub/git/utils.py +48 -0
- infrahub/git/worktree.py +1 -2
- infrahub/git_credential/askpass.py +1 -2
- infrahub/graphql/analyzer.py +12 -0
- infrahub/graphql/app.py +13 -15
- infrahub/graphql/context.py +6 -0
- infrahub/graphql/initialization.py +3 -0
- infrahub/graphql/loaders/node.py +2 -12
- infrahub/graphql/loaders/peers.py +77 -0
- infrahub/graphql/loaders/shared.py +13 -0
- infrahub/graphql/manager.py +13 -10
- infrahub/graphql/mutations/artifact_definition.py +5 -5
- infrahub/graphql/mutations/computed_attribute.py +4 -5
- infrahub/graphql/mutations/graphql_query.py +5 -5
- infrahub/graphql/mutations/ipam.py +50 -70
- infrahub/graphql/mutations/main.py +164 -141
- infrahub/graphql/mutations/menu.py +5 -5
- infrahub/graphql/mutations/models.py +2 -4
- infrahub/graphql/mutations/node_getter/by_default_filter.py +10 -10
- infrahub/graphql/mutations/node_getter/by_hfid.py +1 -3
- infrahub/graphql/mutations/node_getter/by_id.py +1 -3
- infrahub/graphql/mutations/node_getter/interface.py +1 -2
- infrahub/graphql/mutations/proposed_change.py +7 -7
- infrahub/graphql/mutations/relationship.py +67 -35
- infrahub/graphql/mutations/repository.py +8 -8
- infrahub/graphql/mutations/resource_manager.py +3 -3
- infrahub/graphql/mutations/schema.py +4 -4
- infrahub/graphql/mutations/webhook.py +137 -0
- infrahub/graphql/parser.py +4 -4
- infrahub/graphql/queries/diff/tree.py +4 -4
- infrahub/graphql/queries/ipam.py +2 -2
- infrahub/graphql/queries/relationship.py +2 -2
- infrahub/graphql/queries/search.py +2 -2
- infrahub/graphql/resolvers/many_relationship.py +264 -0
- infrahub/graphql/resolvers/resolver.py +13 -110
- infrahub/graphql/subscription/graphql_query.py +2 -0
- infrahub/graphql/types/event.py +20 -11
- infrahub/graphql/types/node.py +2 -2
- infrahub/graphql/utils.py +2 -2
- infrahub/groups/ancestors.py +29 -0
- infrahub/groups/parsers.py +107 -0
- infrahub/menu/generator.py +7 -7
- infrahub/menu/menu.py +0 -10
- infrahub/menu/models.py +117 -16
- infrahub/menu/repository.py +111 -0
- infrahub/menu/utils.py +5 -8
- infrahub/message_bus/messages/__init__.py +1 -11
- infrahub/message_bus/messages/check_generator_run.py +2 -0
- infrahub/message_bus/messages/finalize_validator_execution.py +3 -0
- infrahub/message_bus/messages/request_generatordefinition_check.py +2 -0
- infrahub/message_bus/operations/__init__.py +0 -2
- infrahub/message_bus/operations/check/generator.py +1 -0
- infrahub/message_bus/operations/event/__init__.py +2 -2
- infrahub/message_bus/operations/finalize/validator.py +51 -1
- infrahub/message_bus/operations/requests/generator_definition.py +19 -19
- infrahub/message_bus/operations/requests/proposed_change.py +3 -1
- infrahub/pools/number.py +2 -4
- infrahub/proposed_change/tasks.py +37 -28
- infrahub/pytest_plugin.py +13 -10
- infrahub/server.py +1 -2
- infrahub/services/adapters/event/__init__.py +1 -1
- infrahub/task_manager/event.py +23 -9
- infrahub/tasks/artifact.py +2 -4
- infrahub/telemetry/__init__.py +0 -0
- infrahub/telemetry/constants.py +9 -0
- infrahub/telemetry/database.py +86 -0
- infrahub/telemetry/models.py +65 -0
- infrahub/telemetry/task_manager.py +77 -0
- infrahub/{tasks/telemetry.py → telemetry/tasks.py} +49 -56
- infrahub/telemetry/utils.py +11 -0
- infrahub/trace.py +4 -4
- infrahub/transformations/tasks.py +2 -2
- infrahub/trigger/catalogue.py +2 -5
- infrahub/trigger/constants.py +0 -8
- infrahub/trigger/models.py +14 -1
- infrahub/trigger/setup.py +90 -0
- infrahub/trigger/tasks.py +35 -90
- infrahub/utils.py +11 -1
- infrahub/validators/__init__.py +0 -0
- infrahub/validators/events.py +42 -0
- infrahub/validators/tasks.py +41 -0
- infrahub/webhook/gather.py +17 -0
- infrahub/webhook/models.py +22 -5
- infrahub/webhook/tasks.py +44 -19
- infrahub/webhook/triggers.py +22 -5
- infrahub/workers/infrahub_async.py +2 -2
- infrahub/workers/utils.py +2 -2
- infrahub/workflows/catalogue.py +28 -20
- infrahub/workflows/initialization.py +1 -3
- infrahub/workflows/models.py +1 -1
- infrahub/workflows/utils.py +10 -1
- infrahub_sdk/client.py +27 -8
- infrahub_sdk/config.py +3 -0
- infrahub_sdk/context.py +13 -0
- infrahub_sdk/exceptions.py +6 -0
- infrahub_sdk/generator.py +4 -1
- infrahub_sdk/graphql.py +45 -13
- infrahub_sdk/node.py +69 -20
- infrahub_sdk/protocols_base.py +32 -11
- infrahub_sdk/query_groups.py +6 -35
- infrahub_sdk/schema/__init__.py +55 -26
- infrahub_sdk/schema/main.py +8 -0
- infrahub_sdk/task/__init__.py +10 -0
- infrahub_sdk/task/manager.py +12 -6
- infrahub_sdk/testing/schemas/animal.py +9 -0
- infrahub_sdk/timestamp.py +12 -4
- {infrahub_server-1.2.0b1.dist-info → infrahub_server-1.2.1.dist-info}/METADATA +3 -2
- {infrahub_server-1.2.0b1.dist-info → infrahub_server-1.2.1.dist-info}/RECORD +289 -260
- {infrahub_server-1.2.0b1.dist-info → infrahub_server-1.2.1.dist-info}/entry_points.txt +1 -0
- infrahub_testcontainers/constants.py +2 -0
- infrahub_testcontainers/container.py +157 -12
- infrahub_testcontainers/docker-compose.test.yml +31 -6
- infrahub_testcontainers/helpers.py +18 -73
- infrahub_testcontainers/host.py +41 -0
- infrahub_testcontainers/measurements.py +93 -0
- infrahub_testcontainers/models.py +38 -0
- infrahub_testcontainers/performance_test.py +166 -0
- infrahub_testcontainers/plugin.py +136 -0
- infrahub_testcontainers/prometheus.yml +30 -0
- infrahub/message_bus/messages/event_branch_create.py +0 -11
- infrahub/message_bus/messages/event_branch_delete.py +0 -11
- infrahub/message_bus/messages/event_branch_rebased.py +0 -9
- infrahub/message_bus/messages/event_node_mutated.py +0 -15
- infrahub/message_bus/messages/event_schema_update.py +0 -9
- infrahub/message_bus/operations/event/node.py +0 -20
- infrahub/message_bus/operations/event/schema.py +0 -17
- infrahub/webhook/constants.py +0 -1
- {infrahub_server-1.2.0b1.dist-info → infrahub_server-1.2.1.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.2.0b1.dist-info → infrahub_server-1.2.1.dist-info}/WHEEL +0 -0
|
@@ -5,7 +5,7 @@ import keyword
|
|
|
5
5
|
import os
|
|
6
6
|
from dataclasses import asdict, dataclass
|
|
7
7
|
from enum import Enum
|
|
8
|
-
from typing import TYPE_CHECKING, Any, Callable, Iterable, Literal,
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Callable, Iterable, Literal, overload
|
|
9
9
|
|
|
10
10
|
from infrahub_sdk.utils import compare_lists, intersection
|
|
11
11
|
from pydantic import field_validator
|
|
@@ -25,6 +25,7 @@ if TYPE_CHECKING:
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
NODE_METADATA_ATTRIBUTES = ["_source", "_owner"]
|
|
28
|
+
INHERITED = "INHERITED"
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
@@ -120,7 +121,7 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
|
120
121
|
other: Self,
|
|
121
122
|
get_func: Callable,
|
|
122
123
|
get_map_func: Callable,
|
|
123
|
-
obj_type: type[
|
|
124
|
+
obj_type: type[AttributeSchema | RelationshipSchema],
|
|
124
125
|
) -> HashableModelDiff:
|
|
125
126
|
"""The goal of this function is to reduce the amount of code duplicated between Attribute and Relationship to calculate a diff
|
|
126
127
|
The logic is the same for both, except that the functions we are using to access these objects are differents
|
|
@@ -138,8 +139,8 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
|
138
139
|
reversed_map_other = dict(map(reversed, other_map.items()))
|
|
139
140
|
|
|
140
141
|
# Identify which elements are using the same id on both sides
|
|
141
|
-
clean_local_ids = [id for id in local_map.values() if id is not None]
|
|
142
|
-
clean_other_ids = [id for id in other_map.values() if id is not None]
|
|
142
|
+
clean_local_ids = [id for id in local_map.values() if id is not None and id != INHERITED]
|
|
143
|
+
clean_other_ids = [id for id in other_map.values() if id is not None and id != INHERITED]
|
|
143
144
|
shared_ids = intersection(list1=clean_local_ids, list2=clean_other_ids)
|
|
144
145
|
|
|
145
146
|
# Identify which elements are present on both side based on the name
|
|
@@ -176,16 +177,14 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
|
176
177
|
return elements_diff
|
|
177
178
|
|
|
178
179
|
@overload
|
|
179
|
-
def get_field(
|
|
180
|
-
self, name: str, raise_on_error: Literal[True] = True
|
|
181
|
-
) -> Union[AttributeSchema, RelationshipSchema]: ...
|
|
180
|
+
def get_field(self, name: str, raise_on_error: Literal[True] = True) -> AttributeSchema | RelationshipSchema: ...
|
|
182
181
|
|
|
183
182
|
@overload
|
|
184
183
|
def get_field(
|
|
185
184
|
self, name: str, raise_on_error: Literal[False] = False
|
|
186
|
-
) ->
|
|
185
|
+
) -> AttributeSchema | RelationshipSchema | None: ...
|
|
187
186
|
|
|
188
|
-
def get_field(self, name: str, raise_on_error: bool = True) ->
|
|
187
|
+
def get_field(self, name: str, raise_on_error: bool = True) -> AttributeSchema | RelationshipSchema | None:
|
|
189
188
|
if field := self.get_attribute_or_none(name=name):
|
|
190
189
|
return field
|
|
191
190
|
|
|
@@ -204,7 +203,7 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
|
204
203
|
|
|
205
204
|
raise ValueError(f"Unable to find the attribute {name}")
|
|
206
205
|
|
|
207
|
-
def get_attribute_or_none(self, name: str) ->
|
|
206
|
+
def get_attribute_or_none(self, name: str) -> AttributeSchema | None:
|
|
208
207
|
for item in self.attributes:
|
|
209
208
|
if item.name == name:
|
|
210
209
|
return item
|
|
@@ -230,7 +229,7 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
|
230
229
|
|
|
231
230
|
raise ValueError(f"Unable to find the relationship with the ID: {id}")
|
|
232
231
|
|
|
233
|
-
def get_relationship_or_none(self, name: str) ->
|
|
232
|
+
def get_relationship_or_none(self, name: str) -> RelationshipSchema | None:
|
|
234
233
|
for item in self.relationships:
|
|
235
234
|
if item.name == name:
|
|
236
235
|
return item
|
|
@@ -242,9 +241,9 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
|
242
241
|
@overload
|
|
243
242
|
def get_relationship_by_identifier(
|
|
244
243
|
self, id: str, raise_on_error: Literal[False] = False
|
|
245
|
-
) ->
|
|
244
|
+
) -> RelationshipSchema | None: ...
|
|
246
245
|
|
|
247
|
-
def get_relationship_by_identifier(self, id: str, raise_on_error: bool = True) ->
|
|
246
|
+
def get_relationship_by_identifier(self, id: str, raise_on_error: bool = True) -> RelationshipSchema | None:
|
|
248
247
|
for item in self.relationships:
|
|
249
248
|
if item.identifier == id:
|
|
250
249
|
return item
|
|
@@ -269,13 +268,13 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
|
269
268
|
def get_attributes_name_id_map(self) -> dict[str, str]:
|
|
270
269
|
name_id_map = {}
|
|
271
270
|
for attr in self.attributes:
|
|
272
|
-
name_id_map[attr.name] = attr.id
|
|
271
|
+
name_id_map[attr.name] = INHERITED if attr.inherited else attr.id
|
|
273
272
|
return name_id_map
|
|
274
273
|
|
|
275
274
|
def get_relationship_name_id_map(self) -> dict[str, str]:
|
|
276
275
|
name_id_map = {}
|
|
277
276
|
for rel in self.relationships:
|
|
278
|
-
name_id_map[rel.name] = rel.id
|
|
277
|
+
name_id_map[rel.name] = INHERITED if rel.inherited else rel.id
|
|
279
278
|
return name_id_map
|
|
280
279
|
|
|
281
280
|
@property
|
|
@@ -343,7 +342,7 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
|
343
342
|
fields[subpaths[0]] = cls.convert_path_to_graphql_fields(path=subpaths[1])
|
|
344
343
|
return fields
|
|
345
344
|
|
|
346
|
-
def generate_fields_for_display_label(self) ->
|
|
345
|
+
def generate_fields_for_display_label(self) -> dict | None:
|
|
347
346
|
"""Generate a dictionary containing the list of fields that are required
|
|
348
347
|
to generate the display_label.
|
|
349
348
|
|
|
@@ -353,12 +352,12 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
|
353
352
|
if not self.display_labels:
|
|
354
353
|
return None
|
|
355
354
|
|
|
356
|
-
fields: dict[str,
|
|
355
|
+
fields: dict[str, str | None | dict[str, None]] = {}
|
|
357
356
|
for item in self.display_labels:
|
|
358
357
|
fields.update(self.convert_path_to_graphql_fields(path=item))
|
|
359
358
|
return fields
|
|
360
359
|
|
|
361
|
-
def generate_fields_for_hfid(self) ->
|
|
360
|
+
def generate_fields_for_hfid(self) -> dict | None:
|
|
362
361
|
"""Generate a dictionary containing the list of fields that are required
|
|
363
362
|
to generate the hfid.
|
|
364
363
|
|
|
@@ -368,7 +367,7 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
|
368
367
|
if not self.human_friendly_id:
|
|
369
368
|
return None
|
|
370
369
|
|
|
371
|
-
fields: dict[str,
|
|
370
|
+
fields: dict[str, str | None | dict[str, None]] = {}
|
|
372
371
|
for item in self.human_friendly_id:
|
|
373
372
|
fields.update(self.convert_path_to_graphql_fields(path=item))
|
|
374
373
|
return fields
|
|
@@ -381,11 +380,11 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
|
381
380
|
|
|
382
381
|
return value
|
|
383
382
|
|
|
384
|
-
def parse_schema_path(self, path: str, schema:
|
|
383
|
+
def parse_schema_path(self, path: str, schema: SchemaBranch | None = None) -> SchemaAttributePath:
|
|
385
384
|
schema_path = SchemaAttributePath()
|
|
386
|
-
relationship_piece:
|
|
387
|
-
attribute_piece:
|
|
388
|
-
property_piece:
|
|
385
|
+
relationship_piece: str | None = None
|
|
386
|
+
attribute_piece: str | None = None
|
|
387
|
+
property_piece: str | None = None
|
|
389
388
|
|
|
390
389
|
path_parts = path.split("__")
|
|
391
390
|
if path_parts[0] in self.relationship_names:
|
|
@@ -434,33 +433,79 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
|
|
|
434
433
|
def get_unique_constraint_schema_attribute_paths(
|
|
435
434
|
self,
|
|
436
435
|
schema_branch: SchemaBranch,
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
constraint_paths_groups.append(
|
|
443
|
-
[SchemaAttributePath(attribute_schema=attribute_schema, attribute_property_name="value")]
|
|
444
|
-
)
|
|
445
|
-
|
|
446
|
-
if not self.uniqueness_constraints:
|
|
447
|
-
return constraint_paths_groups
|
|
436
|
+
) -> list[SchemaUniquenessConstraintPath]:
|
|
437
|
+
if self.uniqueness_constraints is None:
|
|
438
|
+
return []
|
|
439
|
+
|
|
440
|
+
uniqueness_constraint_paths = []
|
|
448
441
|
|
|
449
442
|
for uniqueness_path_group in self.uniqueness_constraints:
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
443
|
+
attributes_paths = [
|
|
444
|
+
self.parse_schema_path(path=uniqueness_path_part, schema=schema_branch)
|
|
445
|
+
for uniqueness_path_part in uniqueness_path_group
|
|
446
|
+
]
|
|
447
|
+
uniqueness_constraint_type = self.get_uniqueness_constraint_type(
|
|
448
|
+
uniqueness_constraint=set(uniqueness_path_group), schema_branch=schema_branch
|
|
449
|
+
)
|
|
450
|
+
uniqueness_constraint_path = SchemaUniquenessConstraintPath(
|
|
451
|
+
attributes_paths=attributes_paths, typ=uniqueness_constraint_type
|
|
452
|
+
)
|
|
453
|
+
uniqueness_constraint_paths.append(uniqueness_constraint_path)
|
|
454
|
+
|
|
455
|
+
return uniqueness_constraint_paths
|
|
456
|
+
|
|
457
|
+
def convert_hfid_to_uniqueness_constraint(self, schema_branch: SchemaBranch) -> list[str] | None:
|
|
458
|
+
if self.human_friendly_id is None:
|
|
459
|
+
return None
|
|
460
|
+
|
|
461
|
+
uniqueness_constraint = []
|
|
462
|
+
for item in self.human_friendly_id:
|
|
463
|
+
schema_attribute_path = self.parse_schema_path(path=item, schema=schema_branch)
|
|
464
|
+
if schema_attribute_path.is_type_attribute:
|
|
465
|
+
uniqueness_constraint.append(item)
|
|
466
|
+
elif schema_attribute_path.is_type_relationship:
|
|
467
|
+
uniqueness_constraint.append(schema_attribute_path.relationship_schema.name)
|
|
468
|
+
return uniqueness_constraint
|
|
469
|
+
|
|
470
|
+
def get_uniqueness_constraint_type(
|
|
471
|
+
self, uniqueness_constraint: set[str], schema_branch: SchemaBranch
|
|
472
|
+
) -> UniquenessConstraintType:
|
|
473
|
+
hfid = self.convert_hfid_to_uniqueness_constraint(schema_branch=schema_branch)
|
|
474
|
+
if hfid is None:
|
|
475
|
+
return UniquenessConstraintType.STANDARD
|
|
476
|
+
hfid_set = set(hfid)
|
|
477
|
+
if uniqueness_constraint == hfid_set:
|
|
478
|
+
return UniquenessConstraintType.HFID
|
|
479
|
+
if uniqueness_constraint <= hfid_set:
|
|
480
|
+
return UniquenessConstraintType.SUBSET_OF_HFID
|
|
481
|
+
return UniquenessConstraintType.STANDARD
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
@dataclass
|
|
485
|
+
class SchemaUniquenessConstraintPath:
|
|
486
|
+
attributes_paths: list[SchemaAttributePath]
|
|
487
|
+
typ: UniquenessConstraintType
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
class UniquenessConstraintType(Enum):
|
|
491
|
+
HFID = "HFID"
|
|
492
|
+
SUBSET_OF_HFID = "SUBSET_OF_HFID"
|
|
493
|
+
STANDARD = "STANDARD"
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
@dataclass
|
|
497
|
+
class UniquenessConstraintViolation:
|
|
498
|
+
nodes_ids: set[str]
|
|
499
|
+
fields: list[str]
|
|
500
|
+
typ: UniquenessConstraintType
|
|
456
501
|
|
|
457
502
|
|
|
458
503
|
@dataclass
|
|
459
504
|
class SchemaAttributePath:
|
|
460
|
-
relationship_schema:
|
|
461
|
-
related_schema:
|
|
462
|
-
attribute_schema:
|
|
463
|
-
attribute_property_name:
|
|
505
|
+
relationship_schema: RelationshipSchema | None = None
|
|
506
|
+
related_schema: NodeSchema | GenericSchema | None = None
|
|
507
|
+
attribute_schema: AttributeSchema | None = None
|
|
508
|
+
attribute_property_name: str | None = None
|
|
464
509
|
|
|
465
510
|
@property
|
|
466
511
|
def is_type_attribute(self) -> bool:
|
|
@@ -492,6 +537,10 @@ class SchemaAttributePath:
|
|
|
492
537
|
return self.attribute_property_name
|
|
493
538
|
raise AttributePathParsingError("An attribute_property_name was expected but not found")
|
|
494
539
|
|
|
540
|
+
@property
|
|
541
|
+
def attribute_path_as_str(self) -> str:
|
|
542
|
+
return self.active_attribute_schema.name + "__" + self.active_attribute_property_name
|
|
543
|
+
|
|
495
544
|
|
|
496
545
|
@dataclass
|
|
497
546
|
class SchemaAttributePathValue(SchemaAttributePath):
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any
|
|
1
|
+
from typing import Any
|
|
2
2
|
|
|
3
3
|
from pydantic import ConfigDict, Field, model_serializer
|
|
4
4
|
|
|
@@ -8,10 +8,10 @@ from infrahub.core.models import HashableModel
|
|
|
8
8
|
|
|
9
9
|
class ComputedAttribute(HashableModel):
|
|
10
10
|
kind: ComputedAttributeKind
|
|
11
|
-
jinja2_template:
|
|
11
|
+
jinja2_template: str | None = Field(
|
|
12
12
|
default=None, description="The Jinja2 template in string format, required when assignment_type=jinja2"
|
|
13
13
|
)
|
|
14
|
-
transform:
|
|
14
|
+
transform: str | None = Field(
|
|
15
15
|
default=None, description="The Python Transform name or ID, required when assignment_type=transform"
|
|
16
16
|
)
|
|
17
17
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
|
+
from ...generic_schema import GenericSchema
|
|
4
|
+
from ...node_schema import NodeSchema
|
|
3
5
|
from .account import (
|
|
4
6
|
core_account,
|
|
5
7
|
core_account_token,
|
|
@@ -11,6 +13,7 @@ from .account import (
|
|
|
11
13
|
from .artifact import core_artifact, core_artifact_definition, core_artifact_target
|
|
12
14
|
from .builtin import builtin_tag
|
|
13
15
|
from .check import core_check_definition
|
|
16
|
+
from .core import core_node, core_task_target
|
|
14
17
|
from .generator import core_generator_definition, core_generator_instance
|
|
15
18
|
from .graphql_query import core_graphql_query
|
|
16
19
|
from .group import core_generator_group, core_graphql_query_group, core_group, core_standard_group
|
|
@@ -54,27 +57,11 @@ from .propose_change_validator import (
|
|
|
54
57
|
)
|
|
55
58
|
from .repository import core_generic_repository, core_read_only_repository, core_repository
|
|
56
59
|
from .resource_pool import core_ip_address_pool, core_ip_prefix_pool, core_number_pool, core_resource_pool
|
|
57
|
-
from .template import core_object_template
|
|
60
|
+
from .template import core_object_component_template, core_object_template
|
|
58
61
|
from .transform import core_transform, core_transform_jinja2, core_transform_python
|
|
59
62
|
from .webhook import core_custom_webhook, core_standard_webhook, core_webhook
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
"name": "Node",
|
|
63
|
-
"namespace": "Core",
|
|
64
|
-
"include_in_menu": False,
|
|
65
|
-
"description": "Base Node in Infrahub.",
|
|
66
|
-
"label": "Node",
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
core_task_target = {
|
|
70
|
-
"name": "TaskTarget",
|
|
71
|
-
"include_in_menu": False,
|
|
72
|
-
"namespace": "Core",
|
|
73
|
-
"description": "Extend a node to be associated with tasks",
|
|
74
|
-
"label": "Task Target",
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
core_models: dict[str, Any] = {
|
|
64
|
+
core_models_mixed: dict[str, list] = {
|
|
78
65
|
"generics": [
|
|
79
66
|
core_node,
|
|
80
67
|
lineage_owner,
|
|
@@ -98,6 +85,7 @@ core_models: dict[str, Any] = {
|
|
|
98
85
|
core_base_permission,
|
|
99
86
|
core_credential,
|
|
100
87
|
core_object_template,
|
|
88
|
+
core_object_component_template,
|
|
101
89
|
generic_menu_item,
|
|
102
90
|
],
|
|
103
91
|
"nodes": [
|
|
@@ -117,7 +105,7 @@ core_models: dict[str, Any] = {
|
|
|
117
105
|
core_object_thread,
|
|
118
106
|
core_change_comment,
|
|
119
107
|
core_thread_comment,
|
|
120
|
-
core_repository
|
|
108
|
+
core_repository,
|
|
121
109
|
core_read_only_repository,
|
|
122
110
|
core_transform_jinja2,
|
|
123
111
|
core_data_check,
|
|
@@ -151,3 +139,9 @@ core_models: dict[str, Any] = {
|
|
|
151
139
|
core_account_group,
|
|
152
140
|
],
|
|
153
141
|
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
core_models: dict[str, Any] = {
|
|
145
|
+
"generics": [item.to_dict() if isinstance(item, GenericSchema) else item for item in core_models_mixed["generics"]],
|
|
146
|
+
"nodes": [item.to_dict() if isinstance(item, NodeSchema) else item for item in core_models_mixed["nodes"]],
|
|
147
|
+
}
|