infrahub-server 1.2.11__py3-none-any.whl → 1.3.0b1__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 +86 -0
- infrahub/actions/gather.py +114 -0
- infrahub/actions/models.py +241 -0
- infrahub/actions/parsers.py +104 -0
- infrahub/actions/schema.py +382 -0
- infrahub/actions/tasks.py +126 -0
- infrahub/actions/triggers.py +21 -0
- infrahub/cli/db.py +1 -2
- infrahub/core/account.py +24 -47
- infrahub/core/attribute.py +13 -15
- infrahub/core/constants/__init__.py +5 -0
- infrahub/core/constants/infrahubkind.py +9 -0
- infrahub/core/convert_object_type/__init__.py +0 -0
- infrahub/core/convert_object_type/conversion.py +122 -0
- infrahub/core/convert_object_type/schema_mapping.py +56 -0
- infrahub/core/diff/query/all_conflicts.py +1 -5
- infrahub/core/diff/query/artifact.py +10 -20
- infrahub/core/diff/query/diff_get.py +3 -6
- infrahub/core/diff/query/field_summary.py +2 -4
- infrahub/core/diff/query/merge.py +70 -123
- infrahub/core/diff/query/save.py +20 -32
- infrahub/core/diff/query/summary_counts_enricher.py +34 -54
- infrahub/core/manager.py +14 -11
- infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -4
- 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/m024_missing_hierarchy_backfill.py +1 -2
- infrahub/core/migrations/query/attribute_add.py +1 -2
- infrahub/core/migrations/query/attribute_rename.py +5 -10
- 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 -17
- infrahub/core/migrations/schema/node_attribute_remove.py +4 -8
- infrahub/core/migrations/schema/node_remove.py +19 -19
- infrahub/core/models.py +29 -2
- infrahub/core/node/__init__.py +90 -18
- 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/protocols.py +56 -0
- infrahub/core/protocols_base.py +3 -0
- infrahub/core/query/__init__.py +2 -2
- infrahub/core/query/diff.py +19 -32
- infrahub/core/query/ipam.py +10 -20
- infrahub/core/query/node.py +28 -46
- infrahub/core/query/relationship.py +53 -32
- infrahub/core/query/resource_manager.py +1 -2
- infrahub/core/query/subquery.py +2 -4
- infrahub/core/relationship/model.py +3 -0
- infrahub/core/schema/__init__.py +2 -1
- infrahub/core/schema/attribute_parameters.py +160 -0
- infrahub/core/schema/attribute_schema.py +111 -8
- infrahub/core/schema/basenode_schema.py +25 -1
- infrahub/core/schema/definitions/core/__init__.py +29 -1
- infrahub/core/schema/definitions/core/group.py +45 -0
- infrahub/core/schema/definitions/internal.py +27 -4
- infrahub/core/schema/generated/attribute_schema.py +16 -3
- infrahub/core/schema/manager.py +3 -0
- infrahub/core/schema/schema_branch.py +67 -7
- infrahub/core/validators/__init__.py +13 -1
- 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 +3 -8
- infrahub/core/validators/uniqueness/query.py +5 -9
- infrahub/database/__init__.py +11 -2
- infrahub/events/group_action.py +1 -0
- infrahub/git/base.py +5 -3
- infrahub/git/integrator.py +102 -3
- 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 +62 -0
- infrahub/graphql/mutations/main.py +24 -175
- infrahub/graphql/mutations/proposed_change.py +20 -17
- infrahub/graphql/mutations/resource_manager.py +62 -6
- infrahub/graphql/queries/convert_object_type_mapping.py +36 -0
- infrahub/graphql/queries/resource_manager.py +7 -1
- infrahub/graphql/schema.py +6 -0
- infrahub/menu/menu.py +31 -0
- infrahub/message_bus/messages/__init__.py +0 -10
- infrahub/message_bus/operations/__init__.py +0 -8
- infrahub/patch/queries/consolidate_duplicated_nodes.py +3 -6
- infrahub/patch/queries/delete_duplicated_edges.py +5 -10
- infrahub/pools/number.py +5 -3
- infrahub/prefect_server/models.py +1 -19
- infrahub/proposed_change/models.py +68 -3
- infrahub/proposed_change/tasks.py +907 -30
- infrahub/task_manager/models.py +10 -6
- infrahub/trigger/catalogue.py +2 -0
- infrahub/trigger/models.py +18 -2
- infrahub/trigger/tasks.py +3 -1
- infrahub/types.py +6 -0
- infrahub/workflows/catalogue.py +76 -0
- infrahub_sdk/client.py +43 -10
- 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} +50 -749
- 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/query_groups.py +13 -2
- 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_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/METADATA +4 -4
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/RECORD +134 -122
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/WHEEL +1 -1
- 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.11.dist-info → infrahub_server-1.3.0b1.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
|
+
from infrahub.actions.schema import (
|
|
4
|
+
core_action,
|
|
5
|
+
core_generator_action,
|
|
6
|
+
core_group_action,
|
|
7
|
+
core_group_trigger_rule,
|
|
8
|
+
core_node_trigger_attribute_match,
|
|
9
|
+
core_node_trigger_match,
|
|
10
|
+
core_node_trigger_relationship_match,
|
|
11
|
+
core_node_trigger_rule,
|
|
12
|
+
core_trigger_rule,
|
|
13
|
+
)
|
|
14
|
+
|
|
3
15
|
from ...generic_schema import GenericSchema
|
|
4
16
|
from ...node_schema import NodeSchema
|
|
5
17
|
from .account import (
|
|
@@ -16,7 +28,13 @@ from .check import core_check_definition
|
|
|
16
28
|
from .core import core_node, core_task_target
|
|
17
29
|
from .generator import core_generator_definition, core_generator_instance
|
|
18
30
|
from .graphql_query import core_graphql_query
|
|
19
|
-
from .group import
|
|
31
|
+
from .group import (
|
|
32
|
+
core_generator_group,
|
|
33
|
+
core_graphql_query_group,
|
|
34
|
+
core_group,
|
|
35
|
+
core_repository_group,
|
|
36
|
+
core_standard_group,
|
|
37
|
+
)
|
|
20
38
|
from .ipam import builtin_ip_address, builtin_ip_prefix, builtin_ipam, core_ipam_namespace
|
|
21
39
|
from .lineage import lineage_owner, lineage_source
|
|
22
40
|
from .menu import generic_menu_item, menu_item
|
|
@@ -69,6 +87,9 @@ from .webhook import core_custom_webhook, core_standard_webhook, core_webhook
|
|
|
69
87
|
|
|
70
88
|
core_models_mixed: dict[str, list] = {
|
|
71
89
|
"generics": [
|
|
90
|
+
core_action,
|
|
91
|
+
core_trigger_rule,
|
|
92
|
+
core_node_trigger_match,
|
|
72
93
|
core_node,
|
|
73
94
|
lineage_owner,
|
|
74
95
|
core_profile_schema_definition,
|
|
@@ -97,12 +118,19 @@ core_models_mixed: dict[str, list] = {
|
|
|
97
118
|
],
|
|
98
119
|
"nodes": [
|
|
99
120
|
menu_item,
|
|
121
|
+
core_group_action,
|
|
100
122
|
core_standard_group,
|
|
101
123
|
core_generator_group,
|
|
102
124
|
core_graphql_query_group,
|
|
125
|
+
core_repository_group,
|
|
103
126
|
builtin_tag,
|
|
104
127
|
core_account,
|
|
105
128
|
core_account_token,
|
|
129
|
+
core_generator_action,
|
|
130
|
+
core_group_trigger_rule,
|
|
131
|
+
core_node_trigger_rule,
|
|
132
|
+
core_node_trigger_attribute_match,
|
|
133
|
+
core_node_trigger_relationship_match,
|
|
106
134
|
core_password_credential,
|
|
107
135
|
core_refresh_token,
|
|
108
136
|
core_proposed_change,
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
from infrahub.core.constants import (
|
|
2
2
|
BranchSupportType,
|
|
3
3
|
InfrahubKind,
|
|
4
|
+
RepositoryObjects,
|
|
4
5
|
)
|
|
5
6
|
from infrahub.core.constants import RelationshipCardinality as Cardinality
|
|
6
7
|
from infrahub.core.constants import RelationshipKind as RelKind
|
|
8
|
+
from infrahub.core.schema.dropdown import DropdownChoice
|
|
7
9
|
|
|
8
10
|
from ...attribute_schema import AttributeSchema as Attr
|
|
9
11
|
from ...generic_schema import GenericSchema
|
|
@@ -80,6 +82,7 @@ core_generator_group = NodeSchema(
|
|
|
80
82
|
generate_profile=False,
|
|
81
83
|
)
|
|
82
84
|
|
|
85
|
+
|
|
83
86
|
core_graphql_query_group = NodeSchema(
|
|
84
87
|
name="GraphQLQueryGroup",
|
|
85
88
|
namespace="Core",
|
|
@@ -106,3 +109,45 @@ core_graphql_query_group = NodeSchema(
|
|
|
106
109
|
),
|
|
107
110
|
],
|
|
108
111
|
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
core_repository_group = NodeSchema(
|
|
115
|
+
name="RepositoryGroup",
|
|
116
|
+
namespace="Core",
|
|
117
|
+
description="Group of nodes associated with a given repository.",
|
|
118
|
+
include_in_menu=False,
|
|
119
|
+
icon="mdi:account-group",
|
|
120
|
+
label="Repository Group",
|
|
121
|
+
default_filter="name__value",
|
|
122
|
+
order_by=["name__value"],
|
|
123
|
+
display_labels=["name__value"],
|
|
124
|
+
branch=BranchSupportType.LOCAL,
|
|
125
|
+
inherit_from=[InfrahubKind.GENERICGROUP],
|
|
126
|
+
generate_profile=False,
|
|
127
|
+
attributes=[
|
|
128
|
+
Attr(
|
|
129
|
+
name="content",
|
|
130
|
+
kind="Dropdown",
|
|
131
|
+
description="Type of data to load, can be either `object` or `menu`",
|
|
132
|
+
choices=[
|
|
133
|
+
DropdownChoice(
|
|
134
|
+
name=RepositoryObjects.OBJECT.value,
|
|
135
|
+
label="Objects",
|
|
136
|
+
),
|
|
137
|
+
DropdownChoice(
|
|
138
|
+
name=RepositoryObjects.MENU.value,
|
|
139
|
+
label="Menus",
|
|
140
|
+
),
|
|
141
|
+
],
|
|
142
|
+
optional=False,
|
|
143
|
+
),
|
|
144
|
+
],
|
|
145
|
+
relationships=[
|
|
146
|
+
Rel(
|
|
147
|
+
name="repository",
|
|
148
|
+
peer=InfrahubKind.GENERICREPOSITORY,
|
|
149
|
+
optional=False,
|
|
150
|
+
cardinality=Cardinality.ONE,
|
|
151
|
+
),
|
|
152
|
+
],
|
|
153
|
+
)
|
|
@@ -31,6 +31,12 @@ from infrahub.core.constants import (
|
|
|
31
31
|
RelationshipKind,
|
|
32
32
|
UpdateSupport,
|
|
33
33
|
)
|
|
34
|
+
from infrahub.core.schema.attribute_parameters import (
|
|
35
|
+
AttributeParameters,
|
|
36
|
+
NumberAttributeParameters,
|
|
37
|
+
NumberPoolParameters,
|
|
38
|
+
TextAttributeParameters,
|
|
39
|
+
)
|
|
34
40
|
from infrahub.core.schema.attribute_schema import AttributeSchema
|
|
35
41
|
from infrahub.core.schema.computed_attribute import ComputedAttribute
|
|
36
42
|
from infrahub.core.schema.dropdown import DropdownChoice
|
|
@@ -47,7 +53,7 @@ class SchemaAttribute(BaseModel):
|
|
|
47
53
|
kind: str
|
|
48
54
|
description: str
|
|
49
55
|
extra: ExtraField
|
|
50
|
-
internal_kind: type[Any] | GenericAlias | None = None
|
|
56
|
+
internal_kind: type[Any] | GenericAlias | list[type[Any]] | None = None
|
|
51
57
|
regex: str | None = None
|
|
52
58
|
unique: bool | None = None
|
|
53
59
|
optional: bool | None = None
|
|
@@ -93,6 +99,9 @@ class SchemaAttribute(BaseModel):
|
|
|
93
99
|
if isinstance(self.internal_kind, GenericAlias):
|
|
94
100
|
return str(self.internal_kind)
|
|
95
101
|
|
|
102
|
+
if isinstance(self.internal_kind, list):
|
|
103
|
+
return " | ".join([internal_kind.__name__ for internal_kind in self.internal_kind])
|
|
104
|
+
|
|
96
105
|
if self.internal_kind and self.kind == "List":
|
|
97
106
|
return f"list[{self.internal_kind.__name__}]"
|
|
98
107
|
|
|
@@ -506,21 +515,21 @@ attribute_schema = SchemaNode(
|
|
|
506
515
|
SchemaAttribute(
|
|
507
516
|
name="regex",
|
|
508
517
|
kind="Text",
|
|
509
|
-
description="Regex uses to limit the characters allowed in for the attributes.",
|
|
518
|
+
description="Regex uses to limit the characters allowed in for the attributes. (deprecated: please use parameters.regex instead)",
|
|
510
519
|
optional=True,
|
|
511
520
|
extra={"update": UpdateSupport.VALIDATE_CONSTRAINT},
|
|
512
521
|
),
|
|
513
522
|
SchemaAttribute(
|
|
514
523
|
name="max_length",
|
|
515
524
|
kind="Number",
|
|
516
|
-
description="Set a maximum number of characters allowed for a given attribute.",
|
|
525
|
+
description="Set a maximum number of characters allowed for a given attribute. (deprecated: please use parameters.max_length instead)",
|
|
517
526
|
optional=True,
|
|
518
527
|
extra={"update": UpdateSupport.VALIDATE_CONSTRAINT},
|
|
519
528
|
),
|
|
520
529
|
SchemaAttribute(
|
|
521
530
|
name="min_length",
|
|
522
531
|
kind="Number",
|
|
523
|
-
description="Set a minimum number of characters allowed for a given attribute.",
|
|
532
|
+
description="Set a minimum number of characters allowed for a given attribute. (deprecated: please use parameters.min_length instead)",
|
|
524
533
|
optional=True,
|
|
525
534
|
extra={"update": UpdateSupport.VALIDATE_CONSTRAINT},
|
|
526
535
|
),
|
|
@@ -617,6 +626,20 @@ attribute_schema = SchemaNode(
|
|
|
617
626
|
optional=True,
|
|
618
627
|
extra={"update": UpdateSupport.ALLOWED},
|
|
619
628
|
),
|
|
629
|
+
SchemaAttribute(
|
|
630
|
+
name="parameters",
|
|
631
|
+
kind="JSON",
|
|
632
|
+
internal_kind=[
|
|
633
|
+
AttributeParameters,
|
|
634
|
+
TextAttributeParameters,
|
|
635
|
+
NumberAttributeParameters,
|
|
636
|
+
NumberPoolParameters,
|
|
637
|
+
],
|
|
638
|
+
optional=True,
|
|
639
|
+
description="Extra parameters specific to this kind of attribute",
|
|
640
|
+
extra={"update": UpdateSupport.VALIDATE_CONSTRAINT},
|
|
641
|
+
default_factory="AttributeParameters",
|
|
642
|
+
),
|
|
620
643
|
SchemaAttribute(
|
|
621
644
|
name="deprecation",
|
|
622
645
|
kind="Text",
|
|
@@ -8,6 +8,12 @@ from pydantic import Field
|
|
|
8
8
|
|
|
9
9
|
from infrahub.core.constants import AllowOverrideType, BranchSupportType, HashableModelState
|
|
10
10
|
from infrahub.core.models import HashableModel
|
|
11
|
+
from infrahub.core.schema.attribute_parameters import (
|
|
12
|
+
AttributeParameters, # noqa: TC001
|
|
13
|
+
NumberAttributeParameters, # noqa: TC001
|
|
14
|
+
NumberPoolParameters, # noqa: TC001
|
|
15
|
+
TextAttributeParameters, # noqa: TC001
|
|
16
|
+
)
|
|
11
17
|
from infrahub.core.schema.computed_attribute import ComputedAttribute # noqa: TC001
|
|
12
18
|
from infrahub.core.schema.dropdown import DropdownChoice # noqa: TC001
|
|
13
19
|
|
|
@@ -44,17 +50,17 @@ class GeneratedAttributeSchema(HashableModel):
|
|
|
44
50
|
)
|
|
45
51
|
regex: str | None = Field(
|
|
46
52
|
default=None,
|
|
47
|
-
description="Regex uses to limit the characters allowed in for the attributes.",
|
|
53
|
+
description="Regex uses to limit the characters allowed in for the attributes. (deprecated: please use parameters.regex instead)",
|
|
48
54
|
json_schema_extra={"update": "validate_constraint"},
|
|
49
55
|
)
|
|
50
56
|
max_length: int | None = Field(
|
|
51
57
|
default=None,
|
|
52
|
-
description="Set a maximum number of characters allowed for a given attribute.",
|
|
58
|
+
description="Set a maximum number of characters allowed for a given attribute. (deprecated: please use parameters.max_length instead)",
|
|
53
59
|
json_schema_extra={"update": "validate_constraint"},
|
|
54
60
|
)
|
|
55
61
|
min_length: int | None = Field(
|
|
56
62
|
default=None,
|
|
57
|
-
description="Set a minimum number of characters allowed for a given attribute.",
|
|
63
|
+
description="Set a minimum number of characters allowed for a given attribute. (deprecated: please use parameters.min_length instead)",
|
|
58
64
|
json_schema_extra={"update": "validate_constraint"},
|
|
59
65
|
)
|
|
60
66
|
label: str | None = Field(
|
|
@@ -112,6 +118,13 @@ class GeneratedAttributeSchema(HashableModel):
|
|
|
112
118
|
description="Type of allowed override for the attribute.",
|
|
113
119
|
json_schema_extra={"update": "allowed"},
|
|
114
120
|
)
|
|
121
|
+
parameters: AttributeParameters | TextAttributeParameters | NumberAttributeParameters | NumberPoolParameters = (
|
|
122
|
+
Field(
|
|
123
|
+
default_factory=AttributeParameters,
|
|
124
|
+
description="Extra parameters specific to this kind of attribute",
|
|
125
|
+
json_schema_extra={"update": "validate_constraint"},
|
|
126
|
+
)
|
|
127
|
+
)
|
|
115
128
|
deprecation: str | None = Field(
|
|
116
129
|
default=None,
|
|
117
130
|
description="Mark attribute as deprecated and provide a user-friendly message to display",
|
infrahub/core/schema/manager.py
CHANGED
|
@@ -5,6 +5,7 @@ import hashlib
|
|
|
5
5
|
from collections import defaultdict
|
|
6
6
|
from itertools import chain, combinations
|
|
7
7
|
from typing import Any
|
|
8
|
+
from uuid import uuid4
|
|
8
9
|
|
|
9
10
|
from infrahub_sdk.template import Jinja2Template
|
|
10
11
|
from infrahub_sdk.template.exceptions import JinjaTemplateError, JinjaTemplateOperationViolationError
|
|
@@ -49,6 +50,8 @@ from infrahub.core.schema import (
|
|
|
49
50
|
SchemaRoot,
|
|
50
51
|
TemplateSchema,
|
|
51
52
|
)
|
|
53
|
+
from infrahub.core.schema.attribute_parameters import NumberPoolParameters
|
|
54
|
+
from infrahub.core.schema.attribute_schema import get_attribute_schema_class_for_kind
|
|
52
55
|
from infrahub.core.schema.definitions.core import core_profile_schema_definition
|
|
53
56
|
from infrahub.core.validators import CONSTRAINT_VALIDATOR_MAP
|
|
54
57
|
from infrahub.exceptions import SchemaNotFoundError, ValidationError
|
|
@@ -517,6 +520,7 @@ class SchemaBranch:
|
|
|
517
520
|
self.validate_names()
|
|
518
521
|
self.validate_kinds()
|
|
519
522
|
self.validate_computed_attributes()
|
|
523
|
+
self.validate_attribute_parameters()
|
|
520
524
|
self.validate_default_values()
|
|
521
525
|
self.validate_count_against_cardinality()
|
|
522
526
|
self.validate_identifiers()
|
|
@@ -994,6 +998,58 @@ class SchemaBranch:
|
|
|
994
998
|
f"{node.kind}: Relationship {rel.name!r} is referring an invalid peer {rel.peer!r}"
|
|
995
999
|
) from None
|
|
996
1000
|
|
|
1001
|
+
def validate_attribute_parameters(self) -> None:
|
|
1002
|
+
for name in self.generics.keys():
|
|
1003
|
+
generic_schema = self.get_generic(name=name, duplicate=False)
|
|
1004
|
+
for attribute in generic_schema.attributes:
|
|
1005
|
+
if (
|
|
1006
|
+
attribute.kind == "NumberPool"
|
|
1007
|
+
and isinstance(attribute.parameters, NumberPoolParameters)
|
|
1008
|
+
and not attribute.parameters.number_pool_id
|
|
1009
|
+
):
|
|
1010
|
+
attribute.parameters.number_pool_id = str(uuid4())
|
|
1011
|
+
|
|
1012
|
+
for name in self.nodes.keys():
|
|
1013
|
+
node_schema = self.get_node(name=name, duplicate=False)
|
|
1014
|
+
for attribute in node_schema.attributes:
|
|
1015
|
+
if (
|
|
1016
|
+
attribute.kind == "NumberPool"
|
|
1017
|
+
and isinstance(attribute.parameters, NumberPoolParameters)
|
|
1018
|
+
and not attribute.parameters.number_pool_id
|
|
1019
|
+
):
|
|
1020
|
+
self._validate_number_pool_parameters(
|
|
1021
|
+
node_schema=node_schema, attribute=attribute, number_pool_parameters=attribute.parameters
|
|
1022
|
+
)
|
|
1023
|
+
|
|
1024
|
+
def _validate_number_pool_parameters(
|
|
1025
|
+
self, node_schema: NodeSchema, attribute: AttributeSchema, number_pool_parameters: NumberPoolParameters
|
|
1026
|
+
) -> None:
|
|
1027
|
+
if attribute.optional:
|
|
1028
|
+
raise ValidationError(f"{node_schema.kind}.{attribute.name} is a NumberPool it can't be optional")
|
|
1029
|
+
|
|
1030
|
+
if not attribute.read_only:
|
|
1031
|
+
raise ValidationError(
|
|
1032
|
+
f"{node_schema.kind}.{attribute.name} is a NumberPool it has to be a read_only attribute"
|
|
1033
|
+
)
|
|
1034
|
+
|
|
1035
|
+
if attribute.inherited:
|
|
1036
|
+
generics_with_attribute = []
|
|
1037
|
+
for generic_name in node_schema.inherit_from:
|
|
1038
|
+
generic_schema = self.get_generic(name=generic_name, duplicate=False)
|
|
1039
|
+
if attribute.name in generic_schema.attribute_names:
|
|
1040
|
+
generic_attribute = generic_schema.get_attribute(name=attribute.name)
|
|
1041
|
+
generics_with_attribute.append(generic_schema)
|
|
1042
|
+
if isinstance(generic_attribute.parameters, NumberPoolParameters):
|
|
1043
|
+
number_pool_parameters.number_pool_id = generic_attribute.parameters.number_pool_id
|
|
1044
|
+
|
|
1045
|
+
if len(generics_with_attribute) > 1:
|
|
1046
|
+
raise ValidationError(
|
|
1047
|
+
f"{node_schema.kind}.{attribute.name} is a NumberPool inherited from more than one generic"
|
|
1048
|
+
)
|
|
1049
|
+
|
|
1050
|
+
else:
|
|
1051
|
+
number_pool_parameters.number_pool_id = str(uuid4())
|
|
1052
|
+
|
|
997
1053
|
def validate_computed_attributes(self) -> None:
|
|
998
1054
|
self.computed_attributes = ComputedAttributes()
|
|
999
1055
|
for name in self.nodes.keys():
|
|
@@ -1136,7 +1192,7 @@ class SchemaBranch:
|
|
|
1136
1192
|
self.set(name=name, schema=node)
|
|
1137
1193
|
|
|
1138
1194
|
def process_labels(self) -> None:
|
|
1139
|
-
def check_if_need_to_update_label(node) -> bool:
|
|
1195
|
+
def check_if_need_to_update_label(node: MainSchemaTypes) -> bool:
|
|
1140
1196
|
if not node.label:
|
|
1141
1197
|
return True
|
|
1142
1198
|
for item in node.relationships + node.attributes:
|
|
@@ -1812,12 +1868,14 @@ class SchemaBranch:
|
|
|
1812
1868
|
def generate_profile_from_node(self, node: NodeSchema) -> ProfileSchema:
|
|
1813
1869
|
core_profile_schema = self.get(name=InfrahubKind.PROFILE, duplicate=False)
|
|
1814
1870
|
core_name_attr = core_profile_schema.get_attribute(name="profile_name")
|
|
1815
|
-
|
|
1871
|
+
name_attr_schema_class = get_attribute_schema_class_for_kind(kind=core_name_attr.kind)
|
|
1872
|
+
profile_name_attr = name_attr_schema_class(
|
|
1816
1873
|
**core_name_attr.model_dump(exclude=["id", "inherited"]),
|
|
1817
1874
|
)
|
|
1818
1875
|
profile_name_attr.branch = node.branch
|
|
1819
1876
|
core_priority_attr = core_profile_schema.get_attribute(name="profile_priority")
|
|
1820
|
-
|
|
1877
|
+
priority_attr_schema_class = get_attribute_schema_class_for_kind(kind=core_priority_attr.kind)
|
|
1878
|
+
profile_priority_attr = priority_attr_schema_class(
|
|
1821
1879
|
**core_priority_attr.model_dump(exclude=["id", "inherited"]),
|
|
1822
1880
|
)
|
|
1823
1881
|
profile_priority_attr.branch = node.branch
|
|
@@ -1848,8 +1906,8 @@ class SchemaBranch:
|
|
|
1848
1906
|
for node_attr in node.attributes:
|
|
1849
1907
|
if node_attr.read_only or node_attr.optional is False:
|
|
1850
1908
|
continue
|
|
1851
|
-
|
|
1852
|
-
attr =
|
|
1909
|
+
attr_schema_class = get_attribute_schema_class_for_kind(kind=node_attr.kind)
|
|
1910
|
+
attr = attr_schema_class(
|
|
1853
1911
|
optional=True,
|
|
1854
1912
|
**node_attr.model_dump(exclude=["id", "unique", "optional", "read_only", "default_value", "inherited"]),
|
|
1855
1913
|
)
|
|
@@ -1973,7 +2031,8 @@ class SchemaBranch:
|
|
|
1973
2031
|
else self.get(name=InfrahubKind.OBJECTTEMPLATE, duplicate=False)
|
|
1974
2032
|
)
|
|
1975
2033
|
core_name_attr = core_template_schema.get_attribute(name=OBJECT_TEMPLATE_NAME_ATTR)
|
|
1976
|
-
|
|
2034
|
+
name_attr_schema_class = get_attribute_schema_class_for_kind(kind=core_name_attr.kind)
|
|
2035
|
+
template_name_attr = name_attr_schema_class(
|
|
1977
2036
|
**core_name_attr.model_dump(exclude=["id", "inherited"]),
|
|
1978
2037
|
)
|
|
1979
2038
|
template_name_attr.branch = node.branch
|
|
@@ -2033,7 +2092,8 @@ class SchemaBranch:
|
|
|
2033
2092
|
if node_attr.unique or node_attr.read_only:
|
|
2034
2093
|
continue
|
|
2035
2094
|
|
|
2036
|
-
|
|
2095
|
+
attr_schema_class = get_attribute_schema_class_for_kind(kind=node_attr.kind)
|
|
2096
|
+
attr = attr_schema_class(
|
|
2037
2097
|
optional=node_attr.optional if is_autogenerated_subtemplate else True,
|
|
2038
2098
|
**node_attr.model_dump(exclude=["id", "unique", "optional", "read_only"]),
|
|
2039
2099
|
)
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
from infrahub.core.validators.attribute.min_max import AttributeNumberChecker
|
|
2
|
+
|
|
1
3
|
from .attribute.choices import AttributeChoicesChecker
|
|
2
4
|
from .attribute.enum import AttributeEnumChecker
|
|
3
5
|
from .attribute.kind import AttributeKindChecker
|
|
4
6
|
from .attribute.length import AttributeLengthChecker
|
|
7
|
+
from .attribute.number_pool import AttributeNumberPoolChecker
|
|
5
8
|
from .attribute.optional import AttributeOptionalChecker
|
|
6
9
|
from .attribute.regex import AttributeRegexChecker
|
|
7
10
|
from .attribute.unique import AttributeUniquenessChecker
|
|
11
|
+
from .enum import ConstraintIdentifier
|
|
8
12
|
from .interface import ConstraintCheckerInterface
|
|
9
13
|
from .node.attribute import NodeAttributeAddChecker
|
|
10
14
|
from .node.generate_profile import NodeGenerateProfileChecker
|
|
@@ -17,11 +21,19 @@ from .relationship.peer import RelationshipPeerChecker
|
|
|
17
21
|
from .uniqueness.checker import UniquenessChecker
|
|
18
22
|
|
|
19
23
|
CONSTRAINT_VALIDATOR_MAP: dict[str, type[ConstraintCheckerInterface] | None] = {
|
|
24
|
+
"attribute.kind.update": AttributeKindChecker,
|
|
20
25
|
"attribute.regex.update": AttributeRegexChecker,
|
|
26
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_REGEX_UPDATE.value: AttributeRegexChecker,
|
|
21
27
|
"attribute.enum.update": AttributeEnumChecker,
|
|
22
|
-
"attribute.kind.update": AttributeKindChecker,
|
|
23
28
|
"attribute.min_length.update": AttributeLengthChecker,
|
|
24
29
|
"attribute.max_length.update": AttributeLengthChecker,
|
|
30
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_MIN_LENGTH_UPDATE.value: AttributeLengthChecker,
|
|
31
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_MAX_LENGTH_UPDATE.value: AttributeLengthChecker,
|
|
32
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_MIN_VALUE_UPDATE.value: AttributeNumberChecker,
|
|
33
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_MAX_VALUE_UPDATE.value: AttributeNumberChecker,
|
|
34
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_EXCLUDED_VALUES_UPDATE.value: AttributeNumberChecker,
|
|
35
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_START_RANGE_UPDATE: AttributeNumberPoolChecker,
|
|
36
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_END_RANGE_UPDATE: AttributeNumberPoolChecker,
|
|
25
37
|
"attribute.unique.update": AttributeUniquenessChecker,
|
|
26
38
|
"attribute.optional.update": AttributeOptionalChecker,
|
|
27
39
|
"attribute.choices.update": AttributeChoicesChecker,
|
|
@@ -31,8 +31,7 @@ class AttributeChoicesUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
|
31
31
|
|
|
32
32
|
query = """
|
|
33
33
|
MATCH p = (n:%(node_kind)s)
|
|
34
|
-
CALL {
|
|
35
|
-
WITH n
|
|
34
|
+
CALL (n) {
|
|
36
35
|
MATCH path = (root:Root)<-[rr:IS_PART_OF]-(n)-[ra:HAS_ATTRIBUTE]-(:Attribute { name: $attr_name } )-[rv:HAS_VALUE]-(av:AttributeValue)
|
|
37
36
|
WHERE all(
|
|
38
37
|
r in relationships(path)
|
|
@@ -43,7 +42,6 @@ class AttributeChoicesUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
|
43
42
|
LIMIT 1
|
|
44
43
|
}
|
|
45
44
|
WITH full_path, node, attribute_value, value_relationship
|
|
46
|
-
WITH full_path, node, attribute_value, value_relationship
|
|
47
45
|
WHERE all(r in relationships(full_path) WHERE r.status = "active")
|
|
48
46
|
AND attribute_value IS NOT NULL
|
|
49
47
|
AND attribute_value <> $null_value
|
|
@@ -30,8 +30,7 @@ class AttributeEnumUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
|
30
30
|
self.params["null_value"] = NULL_VALUE
|
|
31
31
|
query = """
|
|
32
32
|
MATCH (n:%(node_kind)s)
|
|
33
|
-
CALL {
|
|
34
|
-
WITH n
|
|
33
|
+
CALL (n) {
|
|
35
34
|
MATCH path = (root:Root)<-[rr:IS_PART_OF]-(n)-[ra:HAS_ATTRIBUTE]-(:Attribute { name: $attr_name } )-[rv:HAS_VALUE]-(av:AttributeValue)
|
|
36
35
|
WHERE all(
|
|
37
36
|
r in relationships(path)
|
|
@@ -42,7 +41,6 @@ class AttributeEnumUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
|
42
41
|
LIMIT 1
|
|
43
42
|
}
|
|
44
43
|
WITH full_path, node, attribute_value, value_relationship
|
|
45
|
-
WITH full_path, node, attribute_value, value_relationship
|
|
46
44
|
WHERE all(r in relationships(full_path) WHERE r.status = "active")
|
|
47
45
|
AND attribute_value IS NOT NULL
|
|
48
46
|
AND attribute_value <> $null_value
|
|
@@ -37,8 +37,7 @@ class AttributeKindUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
|
37
37
|
|
|
38
38
|
query = """
|
|
39
39
|
MATCH p = (n:%(node_kind)s)
|
|
40
|
-
CALL {
|
|
41
|
-
WITH n
|
|
40
|
+
CALL (n) {
|
|
42
41
|
MATCH path = (root:Root)<-[rr:IS_PART_OF]-(n)-[ra:HAS_ATTRIBUTE]-(:Attribute { name: $attr_name } )-[rv:HAS_VALUE]-(av:AttributeValue)
|
|
43
42
|
WHERE all(
|
|
44
43
|
r in relationships(path)
|
|
@@ -49,7 +48,6 @@ class AttributeKindUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
|
49
48
|
LIMIT 1
|
|
50
49
|
}
|
|
51
50
|
WITH full_path, node, attribute_value, value_relationship
|
|
52
|
-
WITH full_path, node, attribute_value, value_relationship
|
|
53
51
|
WHERE all(r in relationships(full_path) WHERE r.status = "active")
|
|
54
52
|
AND attribute_value IS NOT NULL
|
|
55
53
|
AND attribute_value <> $null_value
|
|
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Any
|
|
|
4
4
|
|
|
5
5
|
from infrahub.core.constants import PathType
|
|
6
6
|
from infrahub.core.path import DataPath, GroupedDataPaths
|
|
7
|
+
from infrahub.core.validators.enum import ConstraintIdentifier
|
|
7
8
|
|
|
8
9
|
from ..interface import ConstraintCheckerInterface
|
|
9
10
|
from ..shared import AttributeSchemaValidatorQuery
|
|
@@ -23,13 +24,12 @@ class AttributeLengthUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
|
23
24
|
self.params.update(branch_params)
|
|
24
25
|
|
|
25
26
|
self.params["attr_name"] = self.attribute_schema.name
|
|
26
|
-
self.params["min_length"] = self.attribute_schema.
|
|
27
|
-
self.params["max_length"] = self.attribute_schema.
|
|
27
|
+
self.params["min_length"] = self.attribute_schema.get_min_length()
|
|
28
|
+
self.params["max_length"] = self.attribute_schema.get_max_length()
|
|
28
29
|
|
|
29
30
|
query = """
|
|
30
31
|
MATCH (n:%(node_kind)s)
|
|
31
|
-
CALL {
|
|
32
|
-
WITH n
|
|
32
|
+
CALL (n) {
|
|
33
33
|
MATCH path = (root:Root)<-[rr:IS_PART_OF]-(n)-[ra:HAS_ATTRIBUTE]-(:Attribute { name: $attr_name } )-[rv:HAS_VALUE]-(av:AttributeValue)
|
|
34
34
|
WHERE all(
|
|
35
35
|
r in relationships(path)
|
|
@@ -40,7 +40,6 @@ class AttributeLengthUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
|
40
40
|
LIMIT 1
|
|
41
41
|
}
|
|
42
42
|
WITH full_path, node, attribute_value, value_relationship
|
|
43
|
-
WITH full_path, node, attribute_value, value_relationship
|
|
44
43
|
WHERE all(r in relationships(full_path) WHERE r.status = "active")
|
|
45
44
|
AND (
|
|
46
45
|
(toInteger($min_length) IS NOT NULL AND size(attribute_value) < toInteger($min_length))
|
|
@@ -79,14 +78,21 @@ class AttributeLengthChecker(ConstraintCheckerInterface):
|
|
|
79
78
|
return "attribute.length.update"
|
|
80
79
|
|
|
81
80
|
def supports(self, request: SchemaConstraintValidatorRequest) -> bool:
|
|
82
|
-
return request.constraint_name in (
|
|
81
|
+
return request.constraint_name in (
|
|
82
|
+
"attribute.min_length.update",
|
|
83
|
+
"attribute.max_length.update",
|
|
84
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_MIN_LENGTH_UPDATE.value,
|
|
85
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_MAX_LENGTH_UPDATE.value,
|
|
86
|
+
)
|
|
83
87
|
|
|
84
88
|
async def check(self, request: SchemaConstraintValidatorRequest) -> list[GroupedDataPaths]:
|
|
85
89
|
grouped_data_paths_list: list[GroupedDataPaths] = []
|
|
86
90
|
if not request.schema_path.field_name:
|
|
87
91
|
raise ValueError("field_name is not defined")
|
|
88
92
|
attribute_schema = request.node_schema.get_attribute(name=request.schema_path.field_name)
|
|
89
|
-
|
|
93
|
+
min_length = attribute_schema.get_min_length()
|
|
94
|
+
max_length = attribute_schema.get_max_length()
|
|
95
|
+
if min_length is None and max_length is None:
|
|
90
96
|
return grouped_data_paths_list
|
|
91
97
|
|
|
92
98
|
for query_class in self.query_classes:
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from infrahub.core.constants import PathType
|
|
6
|
+
from infrahub.core.path import DataPath, GroupedDataPaths
|
|
7
|
+
from infrahub.core.schema.attribute_parameters import NumberAttributeParameters
|
|
8
|
+
from infrahub.core.validators.enum import ConstraintIdentifier
|
|
9
|
+
|
|
10
|
+
from ..interface import ConstraintCheckerInterface
|
|
11
|
+
from ..shared import AttributeSchemaValidatorQuery
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from infrahub.core.branch import Branch
|
|
15
|
+
from infrahub.database import InfrahubDatabase
|
|
16
|
+
|
|
17
|
+
from ..model import SchemaConstraintValidatorRequest
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class AttributeNumberUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
21
|
+
name: str = "attribute_constraints_number_validator"
|
|
22
|
+
|
|
23
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
24
|
+
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
|
|
25
|
+
self.params.update(branch_params)
|
|
26
|
+
|
|
27
|
+
if not isinstance(self.attribute_schema.parameters, NumberAttributeParameters):
|
|
28
|
+
raise ValueError("attribute parameters are not a NumberAttributeParameters")
|
|
29
|
+
|
|
30
|
+
self.params["attr_name"] = self.attribute_schema.name
|
|
31
|
+
self.params["min_value"] = self.attribute_schema.parameters.min_value
|
|
32
|
+
self.params["max_value"] = self.attribute_schema.parameters.max_value
|
|
33
|
+
self.params["excluded_values"] = self.attribute_schema.parameters.get_excluded_single_values()
|
|
34
|
+
self.params["excluded_ranges"] = self.attribute_schema.parameters.get_excluded_ranges()
|
|
35
|
+
|
|
36
|
+
query = """
|
|
37
|
+
MATCH (n:%(node_kind)s)
|
|
38
|
+
CALL (n) {
|
|
39
|
+
MATCH path = (root:Root)<-[rr:IS_PART_OF]-(n)-[ra:HAS_ATTRIBUTE]-(:Attribute { name: $attr_name } )-[rv:HAS_VALUE]-(av:AttributeValue)
|
|
40
|
+
WHERE all(
|
|
41
|
+
r in relationships(path)
|
|
42
|
+
WHERE %(branch_filter)s
|
|
43
|
+
)
|
|
44
|
+
RETURN path as full_path, n as node, rv as value_relationship, av.value as attribute_value
|
|
45
|
+
ORDER BY rv.branch_level DESC, ra.branch_level DESC, rr.branch_level DESC, rv.from DESC, ra.from DESC, rr.from DESC
|
|
46
|
+
LIMIT 1
|
|
47
|
+
}
|
|
48
|
+
WITH full_path, node, attribute_value, value_relationship
|
|
49
|
+
WHERE all(r in relationships(full_path) WHERE r.status = "active")
|
|
50
|
+
AND (
|
|
51
|
+
(toInteger($min_value) IS NOT NULL AND attribute_value < toInteger($min_value))
|
|
52
|
+
OR (toInteger($max_value) IS NOT NULL AND attribute_value > toInteger($max_value))
|
|
53
|
+
OR (size($excluded_values) > 0 AND attribute_value IN $excluded_values)
|
|
54
|
+
OR (size($excluded_ranges) > 0 AND any(range in $excluded_ranges WHERE attribute_value >= range[0] AND attribute_value <= range[1]))
|
|
55
|
+
)
|
|
56
|
+
""" % {"branch_filter": branch_filter, "node_kind": self.node_schema.kind}
|
|
57
|
+
|
|
58
|
+
self.add_to_query(query)
|
|
59
|
+
self.return_labels = ["node.uuid", "value_relationship", "attribute_value"]
|
|
60
|
+
|
|
61
|
+
async def get_paths(self) -> GroupedDataPaths:
|
|
62
|
+
grouped_data_paths = GroupedDataPaths()
|
|
63
|
+
for result in self.results:
|
|
64
|
+
grouped_data_paths.add_data_path(
|
|
65
|
+
DataPath(
|
|
66
|
+
branch=str(result.get("value_relationship").get("branch")),
|
|
67
|
+
path_type=PathType.ATTRIBUTE,
|
|
68
|
+
node_id=str(result.get("node.uuid")),
|
|
69
|
+
field_name=self.attribute_schema.name,
|
|
70
|
+
kind=self.node_schema.kind,
|
|
71
|
+
value=result.get("attribute_value"),
|
|
72
|
+
),
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
return grouped_data_paths
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class AttributeNumberChecker(ConstraintCheckerInterface):
|
|
79
|
+
query_classes = [AttributeNumberUpdateValidatorQuery]
|
|
80
|
+
|
|
81
|
+
def __init__(self, db: InfrahubDatabase, branch: Branch | None = None):
|
|
82
|
+
self.db = db
|
|
83
|
+
self.branch = branch
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def name(self) -> str:
|
|
87
|
+
return "attribute.number.update"
|
|
88
|
+
|
|
89
|
+
def supports(self, request: SchemaConstraintValidatorRequest) -> bool:
|
|
90
|
+
return request.constraint_name in (
|
|
91
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_MIN_VALUE_UPDATE.value,
|
|
92
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_MAX_VALUE_UPDATE.value,
|
|
93
|
+
ConstraintIdentifier.ATTRIBUTE_PARAMETERS_EXCLUDED_VALUES_UPDATE.value,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
async def check(self, request: SchemaConstraintValidatorRequest) -> list[GroupedDataPaths]:
|
|
97
|
+
grouped_data_paths_list: list[GroupedDataPaths] = []
|
|
98
|
+
if not request.schema_path.field_name:
|
|
99
|
+
raise ValueError("field_name is not defined")
|
|
100
|
+
attribute_schema = request.node_schema.get_attribute(name=request.schema_path.field_name)
|
|
101
|
+
if not isinstance(attribute_schema.parameters, NumberAttributeParameters):
|
|
102
|
+
raise ValueError("attribute parameters are not a NumberAttributeParameters")
|
|
103
|
+
|
|
104
|
+
if (
|
|
105
|
+
attribute_schema.parameters.min_value is None
|
|
106
|
+
and attribute_schema.parameters.max_value is None
|
|
107
|
+
and attribute_schema.parameters.excluded_values is None
|
|
108
|
+
):
|
|
109
|
+
return grouped_data_paths_list
|
|
110
|
+
|
|
111
|
+
for query_class in self.query_classes:
|
|
112
|
+
# TODO add exception handling
|
|
113
|
+
query = await query_class.init(
|
|
114
|
+
db=self.db, branch=self.branch, node_schema=request.node_schema, schema_path=request.schema_path
|
|
115
|
+
)
|
|
116
|
+
await query.execute(db=self.db)
|
|
117
|
+
grouped_data_paths_list.append(await query.get_paths())
|
|
118
|
+
return grouped_data_paths_list
|