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.
Files changed (147) hide show
  1. infrahub/actions/constants.py +86 -0
  2. infrahub/actions/gather.py +114 -0
  3. infrahub/actions/models.py +241 -0
  4. infrahub/actions/parsers.py +104 -0
  5. infrahub/actions/schema.py +382 -0
  6. infrahub/actions/tasks.py +126 -0
  7. infrahub/actions/triggers.py +21 -0
  8. infrahub/cli/db.py +1 -2
  9. infrahub/core/account.py +24 -47
  10. infrahub/core/attribute.py +13 -15
  11. infrahub/core/constants/__init__.py +5 -0
  12. infrahub/core/constants/infrahubkind.py +9 -0
  13. infrahub/core/convert_object_type/__init__.py +0 -0
  14. infrahub/core/convert_object_type/conversion.py +122 -0
  15. infrahub/core/convert_object_type/schema_mapping.py +56 -0
  16. infrahub/core/diff/query/all_conflicts.py +1 -5
  17. infrahub/core/diff/query/artifact.py +10 -20
  18. infrahub/core/diff/query/diff_get.py +3 -6
  19. infrahub/core/diff/query/field_summary.py +2 -4
  20. infrahub/core/diff/query/merge.py +70 -123
  21. infrahub/core/diff/query/save.py +20 -32
  22. infrahub/core/diff/query/summary_counts_enricher.py +34 -54
  23. infrahub/core/manager.py +14 -11
  24. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
  25. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -4
  26. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +11 -22
  27. infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -6
  28. infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +1 -2
  29. infrahub/core/migrations/graph/m024_missing_hierarchy_backfill.py +1 -2
  30. infrahub/core/migrations/query/attribute_add.py +1 -2
  31. infrahub/core/migrations/query/attribute_rename.py +5 -10
  32. infrahub/core/migrations/query/delete_element_in_schema.py +19 -17
  33. infrahub/core/migrations/query/node_duplicate.py +19 -21
  34. infrahub/core/migrations/query/relationship_duplicate.py +19 -17
  35. infrahub/core/migrations/schema/node_attribute_remove.py +4 -8
  36. infrahub/core/migrations/schema/node_remove.py +19 -19
  37. infrahub/core/models.py +29 -2
  38. infrahub/core/node/__init__.py +90 -18
  39. infrahub/core/node/create.py +211 -0
  40. infrahub/core/node/resource_manager/number_pool.py +31 -5
  41. infrahub/core/node/standard.py +6 -1
  42. infrahub/core/protocols.py +56 -0
  43. infrahub/core/protocols_base.py +3 -0
  44. infrahub/core/query/__init__.py +2 -2
  45. infrahub/core/query/diff.py +19 -32
  46. infrahub/core/query/ipam.py +10 -20
  47. infrahub/core/query/node.py +28 -46
  48. infrahub/core/query/relationship.py +53 -32
  49. infrahub/core/query/resource_manager.py +1 -2
  50. infrahub/core/query/subquery.py +2 -4
  51. infrahub/core/relationship/model.py +3 -0
  52. infrahub/core/schema/__init__.py +2 -1
  53. infrahub/core/schema/attribute_parameters.py +160 -0
  54. infrahub/core/schema/attribute_schema.py +111 -8
  55. infrahub/core/schema/basenode_schema.py +25 -1
  56. infrahub/core/schema/definitions/core/__init__.py +29 -1
  57. infrahub/core/schema/definitions/core/group.py +45 -0
  58. infrahub/core/schema/definitions/internal.py +27 -4
  59. infrahub/core/schema/generated/attribute_schema.py +16 -3
  60. infrahub/core/schema/manager.py +3 -0
  61. infrahub/core/schema/schema_branch.py +67 -7
  62. infrahub/core/validators/__init__.py +13 -1
  63. infrahub/core/validators/attribute/choices.py +1 -3
  64. infrahub/core/validators/attribute/enum.py +1 -3
  65. infrahub/core/validators/attribute/kind.py +1 -3
  66. infrahub/core/validators/attribute/length.py +13 -7
  67. infrahub/core/validators/attribute/min_max.py +118 -0
  68. infrahub/core/validators/attribute/number_pool.py +106 -0
  69. infrahub/core/validators/attribute/optional.py +1 -4
  70. infrahub/core/validators/attribute/regex.py +5 -6
  71. infrahub/core/validators/attribute/unique.py +1 -3
  72. infrahub/core/validators/determiner.py +18 -2
  73. infrahub/core/validators/enum.py +12 -0
  74. infrahub/core/validators/node/hierarchy.py +3 -6
  75. infrahub/core/validators/query.py +1 -3
  76. infrahub/core/validators/relationship/count.py +6 -12
  77. infrahub/core/validators/relationship/optional.py +2 -4
  78. infrahub/core/validators/relationship/peer.py +3 -8
  79. infrahub/core/validators/uniqueness/query.py +5 -9
  80. infrahub/database/__init__.py +11 -2
  81. infrahub/events/group_action.py +1 -0
  82. infrahub/git/base.py +5 -3
  83. infrahub/git/integrator.py +102 -3
  84. infrahub/graphql/analyzer.py +139 -18
  85. infrahub/graphql/manager.py +4 -0
  86. infrahub/graphql/mutations/action.py +164 -0
  87. infrahub/graphql/mutations/convert_object_type.py +62 -0
  88. infrahub/graphql/mutations/main.py +24 -175
  89. infrahub/graphql/mutations/proposed_change.py +20 -17
  90. infrahub/graphql/mutations/resource_manager.py +62 -6
  91. infrahub/graphql/queries/convert_object_type_mapping.py +36 -0
  92. infrahub/graphql/queries/resource_manager.py +7 -1
  93. infrahub/graphql/schema.py +6 -0
  94. infrahub/menu/menu.py +31 -0
  95. infrahub/message_bus/messages/__init__.py +0 -10
  96. infrahub/message_bus/operations/__init__.py +0 -8
  97. infrahub/patch/queries/consolidate_duplicated_nodes.py +3 -6
  98. infrahub/patch/queries/delete_duplicated_edges.py +5 -10
  99. infrahub/pools/number.py +5 -3
  100. infrahub/prefect_server/models.py +1 -19
  101. infrahub/proposed_change/models.py +68 -3
  102. infrahub/proposed_change/tasks.py +907 -30
  103. infrahub/task_manager/models.py +10 -6
  104. infrahub/trigger/catalogue.py +2 -0
  105. infrahub/trigger/models.py +18 -2
  106. infrahub/trigger/tasks.py +3 -1
  107. infrahub/types.py +6 -0
  108. infrahub/workflows/catalogue.py +76 -0
  109. infrahub_sdk/client.py +43 -10
  110. infrahub_sdk/node/__init__.py +39 -0
  111. infrahub_sdk/node/attribute.py +122 -0
  112. infrahub_sdk/node/constants.py +21 -0
  113. infrahub_sdk/{node.py → node/node.py} +50 -749
  114. infrahub_sdk/node/parsers.py +15 -0
  115. infrahub_sdk/node/property.py +24 -0
  116. infrahub_sdk/node/related_node.py +266 -0
  117. infrahub_sdk/node/relationship.py +302 -0
  118. infrahub_sdk/protocols.py +112 -0
  119. infrahub_sdk/protocols_base.py +34 -2
  120. infrahub_sdk/query_groups.py +13 -2
  121. infrahub_sdk/schema/main.py +1 -0
  122. infrahub_sdk/schema/repository.py +16 -0
  123. infrahub_sdk/spec/object.py +1 -1
  124. infrahub_sdk/store.py +1 -1
  125. infrahub_sdk/testing/schemas/car_person.py +1 -0
  126. {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/METADATA +4 -4
  127. {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/RECORD +134 -122
  128. {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/WHEEL +1 -1
  129. infrahub_testcontainers/container.py +0 -1
  130. infrahub_testcontainers/docker-compose.test.yml +1 -1
  131. infrahub_testcontainers/helpers.py +8 -2
  132. infrahub/message_bus/messages/check_generator_run.py +0 -26
  133. infrahub/message_bus/messages/finalize_validator_execution.py +0 -15
  134. infrahub/message_bus/messages/proposed_change/base_with_diff.py +0 -16
  135. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +0 -11
  136. infrahub/message_bus/messages/request_generatordefinition_check.py +0 -20
  137. infrahub/message_bus/messages/request_proposedchange_pipeline.py +0 -23
  138. infrahub/message_bus/operations/check/__init__.py +0 -3
  139. infrahub/message_bus/operations/check/generator.py +0 -156
  140. infrahub/message_bus/operations/finalize/__init__.py +0 -3
  141. infrahub/message_bus/operations/finalize/validator.py +0 -133
  142. infrahub/message_bus/operations/requests/__init__.py +0 -9
  143. infrahub/message_bus/operations/requests/generator_definition.py +0 -140
  144. infrahub/message_bus/operations/requests/proposed_change.py +0 -629
  145. /infrahub/{message_bus/messages/proposed_change → actions}/__init__.py +0 -0
  146. {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/LICENSE.txt +0 -0
  147. {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/entry_points.txt +0 -0
@@ -23,11 +23,10 @@ MATCH (node_with_dup_edges:Node)-[edge]->(peer)
23
23
  WITH node_with_dup_edges, type(edge) AS edge_type, edge.status AS edge_status, edge.branch AS edge_branch, peer, count(*) AS num_dup_edges
24
24
  WHERE num_dup_edges > 1
25
25
  WITH DISTINCT node_with_dup_edges, edge_type, edge_branch, peer
26
- CALL {
26
+ CALL (node_with_dup_edges, edge_type, edge_branch, peer) {
27
27
  // ------------
28
28
  // Get the earliest active and deleted edges for this branch
29
29
  // ------------
30
- WITH node_with_dup_edges, edge_type, edge_branch, peer
31
30
  MATCH (node_with_dup_edges)-[active_edge {branch: edge_branch, status: "active"}]->(peer)
32
31
  WHERE type(active_edge) = edge_type
33
32
  WITH node_with_dup_edges, edge_type, edge_branch, peer, active_edge
@@ -40,8 +39,7 @@ CALL {
40
39
  // ------------
41
40
  // Plan one active edge update with correct from and to times
42
41
  // ------------
43
- CALL {
44
- WITH node_with_dup_edges, edge_type, edge_branch, peer, active_from, deleted_from
42
+ CALL (node_with_dup_edges, edge_type, edge_branch, peer, active_from, deleted_from) {
45
43
  MATCH (node_with_dup_edges)-[active_e {branch: edge_branch, status: "active"}]->(peer)
46
44
  WHERE type(active_e) = edge_type
47
45
  WITH node_with_dup_edges, edge_type, edge_branch, peer, active_from, deleted_from, active_e
@@ -57,8 +55,7 @@ CALL {
57
55
  // ------------
58
56
  // Plan deletes for all the other active edges of this type on this branch
59
57
  // ------------
60
- CALL {
61
- WITH node_with_dup_edges, edge_type, edge_branch, peer
58
+ CALL (node_with_dup_edges, edge_type, edge_branch, peer) {
62
59
  MATCH (node_with_dup_edges)-[active_e {branch: edge_branch, status: "active"}]->(peer)
63
60
  WHERE type(active_e) = edge_type
64
61
  WITH node_with_dup_edges, peer, active_e
@@ -77,8 +74,7 @@ CALL {
77
74
  // ------------
78
75
  // Plan one deleted edge update with correct from time
79
76
  // ------------
80
- CALL {
81
- WITH node_with_dup_edges, edge_type, edge_branch, peer, deleted_from
77
+ CALL (node_with_dup_edges, edge_type, edge_branch, peer, deleted_from) {
82
78
  MATCH (node_with_dup_edges)-[deleted_e {branch: edge_branch, status: "deleted"}]->(peer)
83
79
  WHERE type(deleted_e) = edge_type
84
80
  WITH node_with_dup_edges, edge_type, edge_branch, peer, deleted_from, deleted_e
@@ -94,8 +90,7 @@ CALL {
94
90
  // ------------
95
91
  // Plan deletes for all the other deleted edges of this type on this branch
96
92
  // ------------
97
- CALL {
98
- WITH node_with_dup_edges, edge_type, edge_branch, peer
93
+ CALL (node_with_dup_edges, edge_type, edge_branch, peer) {
99
94
  MATCH (node_with_dup_edges)-[deleted_e {branch: edge_branch, status: "deleted"}]->(peer)
100
95
  WHERE type(deleted_e) = edge_type
101
96
  WITH node_with_dup_edges, peer, deleted_e
infrahub/pools/number.py CHANGED
@@ -8,7 +8,7 @@ from infrahub.core.registry import registry
8
8
 
9
9
  if TYPE_CHECKING:
10
10
  from infrahub.core.branch import Branch
11
- from infrahub.core.protocols import CoreNode
11
+ from infrahub.core.node.resource_manager.number_pool import CoreNumberPool
12
12
  from infrahub.core.timestamp import Timestamp
13
13
  from infrahub.database import InfrahubDatabase
14
14
 
@@ -20,7 +20,9 @@ class UsedNumber:
20
20
 
21
21
 
22
22
  class NumberUtilizationGetter:
23
- def __init__(self, db: InfrahubDatabase, pool: CoreNode, branch: Branch, at: Timestamp | str | None = None) -> None:
23
+ def __init__(
24
+ self, db: InfrahubDatabase, pool: CoreNumberPool, branch: Branch, at: Timestamp | str | None = None
25
+ ) -> None:
24
26
  self.db = db
25
27
  self.at = at
26
28
  self.pool = pool
@@ -62,4 +64,4 @@ class NumberUtilizationGetter:
62
64
 
63
65
  @property
64
66
  def total_pool_size(self) -> int:
65
- return self.end_range - self.start_range + 1
67
+ return self.end_range - self.start_range + 1 - self.pool.get_attribute_nb_excluded_values()
@@ -1,18 +1,10 @@
1
- from typing import TYPE_CHECKING, Sequence, cast
2
-
3
- from prefect.server.database import PrefectDBInterface, db_injector
4
- from prefect.server.events.filters import EventFilter, EventNameFilter, EventOrder, EventRelatedFilter
1
+ from prefect.server.events.filters import EventFilter, EventNameFilter, EventOrder
5
2
  from prefect.server.events.schemas.events import ReceivedEvent
6
3
  from prefect.server.utilities.schemas import PrefectBaseModel
7
4
  from pydantic import BaseModel, Field
8
5
 
9
- if TYPE_CHECKING:
10
- from sqlalchemy.sql.expression import ColumnExpressionArgument
11
-
12
6
 
13
7
  class InfrahubEventFilter(EventFilter):
14
- matching_related: list[EventRelatedFilter] = Field(default_factory=list)
15
-
16
8
  def set_prefix(self) -> None:
17
9
  if self.event:
18
10
  if self.event.prefix is not None and "infrahub." not in self.event.prefix:
@@ -20,16 +12,6 @@ class InfrahubEventFilter(EventFilter):
20
12
  else:
21
13
  self.event = EventNameFilter(prefix=["infrahub."], name=[], exclude_prefix=None, exclude_name=None)
22
14
 
23
- @db_injector
24
- def build_where_clauses(self, db: PrefectDBInterface) -> Sequence["ColumnExpressionArgument[bool]"]:
25
- result = cast(list["ColumnExpressionArgument[bool]"], super().build_where_clauses())
26
- top_level_filter = self._scoped_event_resources(db)
27
- for matching_related in self.matching_related:
28
- matching_related._top_level_filter = top_level_filter
29
- result.extend(matching_related.build_where_clauses())
30
-
31
- return result
32
-
33
15
  @classmethod
34
16
  def default(cls) -> "InfrahubEventFilter":
35
17
  return cls(event=None, any_resource=None, resource=None, related=None, order=EventOrder.DESC)
@@ -1,10 +1,25 @@
1
+ import uuid
2
+
1
3
  from pydantic import BaseModel, ConfigDict, Field
2
4
 
3
- from infrahub.context import InfrahubContext
4
- from infrahub.message_bus.messages.proposed_change.base_with_diff import BaseProposedChangeWithDiffMessage
5
+ from infrahub.core.constants import CheckType
6
+ from infrahub.generators.models import ProposedChangeGeneratorDefinition
7
+ from infrahub.message_bus import InfrahubMessage
5
8
  from infrahub.message_bus.types import ProposedChangeArtifactDefinition, ProposedChangeBranchDiff
6
9
 
7
10
 
11
+ class BaseProposedChangeWithDiffMessage(InfrahubMessage):
12
+ """Sent trigger the refresh of artifacts that are impacted by the proposed change."""
13
+
14
+ model_config = ConfigDict(arbitrary_types_allowed=True)
15
+
16
+ proposed_change: str = Field(..., description="The unique ID of the Proposed Change")
17
+ source_branch: str = Field(..., description="The source branch of the proposed change")
18
+ source_branch_sync_with_git: bool = Field(..., description="Indicates if the source branch should sync with git")
19
+ destination_branch: str = Field(..., description="The destination branch of the proposed change")
20
+ branch_diff: ProposedChangeBranchDiff = Field(..., description="The calculated diff between the two branches")
21
+
22
+
8
23
  class RequestProposedChangeDataIntegrity(BaseProposedChangeWithDiffMessage):
9
24
  """Sent trigger data integrity checks for a proposed change"""
10
25
 
@@ -42,4 +57,54 @@ class RequestArtifactDefinitionCheck(BaseModel):
42
57
  source_branch_sync_with_git: bool = Field(..., description="Indicates if the source branch should sync with git")
43
58
  destination_branch: str = Field(..., description="The target branch")
44
59
 
45
- context: InfrahubContext = Field(..., description="The context of the task")
60
+
61
+ class RunGeneratorAsCheckModel(BaseModel):
62
+ """A check that runs a generator."""
63
+
64
+ generator_definition: ProposedChangeGeneratorDefinition = Field(..., description="The Generator definition")
65
+ generator_instance: str | None = Field(
66
+ default=None, description="The id of the generator instance if it previously existed"
67
+ )
68
+ commit: str = Field(..., description="The commit to target")
69
+ repository_id: str = Field(..., description="The unique ID of the Repository")
70
+ repository_name: str = Field(..., description="The name of the Repository")
71
+ repository_kind: str = Field(..., description="The kind of the Repository")
72
+ branch_name: str = Field(..., description="The branch where the check is run")
73
+ target_id: str = Field(..., description="The ID of the target object for this generator")
74
+ target_name: str = Field(..., description="Name of the generator target")
75
+ query: str = Field(..., description="The name of the query to use when collecting data")
76
+ variables: dict = Field(..., description="Input variables when running the generator")
77
+ validator_id: str = Field(..., description="The ID of the validator")
78
+ proposed_change: str = Field(..., description="The unique ID of the Proposed Change")
79
+
80
+
81
+ class RequestGeneratorDefinitionCheck(BaseModel):
82
+ """Sent to trigger Generators to run for a proposed change."""
83
+
84
+ model_config = ConfigDict(arbitrary_types_allowed=True)
85
+
86
+ generator_definition: ProposedChangeGeneratorDefinition = Field(..., description="The Generator Definition")
87
+ branch_diff: ProposedChangeBranchDiff = Field(..., description="The calculated diff between the two branches")
88
+ proposed_change: str = Field(..., description="The unique ID of the Proposed Change")
89
+ source_branch: str = Field(..., description="The source branch")
90
+ source_branch_sync_with_git: bool = Field(..., description="Indicates if the source branch should sync with git")
91
+ destination_branch: str = Field(..., description="The target branch")
92
+
93
+
94
+ class RequestProposedChangePipeline(BaseModel):
95
+ """Sent request the start of a pipeline connected to a proposed change."""
96
+
97
+ proposed_change: str = Field(..., description="The unique ID of the proposed change")
98
+ source_branch: str = Field(..., description="The source branch of the proposed change")
99
+ source_branch_sync_with_git: bool = Field(..., description="Indicates if the source branch should sync with git")
100
+ destination_branch: str = Field(..., description="The destination branch of the proposed change")
101
+ check_type: CheckType = Field(
102
+ default=CheckType.ALL, description="Can be used to restrict the pipeline to a specific type of job"
103
+ )
104
+ pipeline_id: uuid.UUID = Field(
105
+ default_factory=uuid.uuid4, description="The unique ID of the execution of this pipeline"
106
+ )
107
+
108
+
109
+ class RequestProposedChangeRefreshArtifacts(BaseProposedChangeWithDiffMessage):
110
+ """Sent trigger the refresh of artifacts that are impacted by the proposed change."""