infrahub-server 1.3.0b1__py3-none-any.whl → 1.3.0b3__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 (81) hide show
  1. infrahub/actions/constants.py +87 -0
  2. infrahub/actions/gather.py +3 -3
  3. infrahub/actions/models.py +10 -8
  4. infrahub/actions/parsers.py +6 -6
  5. infrahub/actions/schema.py +46 -37
  6. infrahub/actions/tasks.py +4 -11
  7. infrahub/branch/__init__.py +0 -0
  8. infrahub/branch/tasks.py +29 -0
  9. infrahub/branch/triggers.py +22 -0
  10. infrahub/cli/db.py +2 -2
  11. infrahub/computed_attribute/gather.py +3 -1
  12. infrahub/computed_attribute/tasks.py +23 -29
  13. infrahub/core/constants/__init__.py +5 -0
  14. infrahub/core/constants/database.py +1 -0
  15. infrahub/core/convert_object_type/conversion.py +1 -1
  16. infrahub/core/diff/query/save.py +67 -40
  17. infrahub/core/diff/query/time_range_query.py +0 -1
  18. infrahub/core/graph/__init__.py +1 -1
  19. infrahub/core/migrations/graph/__init__.py +6 -0
  20. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +0 -2
  21. infrahub/core/migrations/graph/m029_duplicates_cleanup.py +662 -0
  22. infrahub/core/migrations/graph/m030_illegal_edges.py +82 -0
  23. infrahub/core/migrations/query/attribute_add.py +13 -9
  24. infrahub/core/migrations/query/relationship_duplicate.py +0 -1
  25. infrahub/core/migrations/schema/node_remove.py +0 -1
  26. infrahub/core/node/__init__.py +2 -0
  27. infrahub/core/node/base.py +1 -1
  28. infrahub/core/path.py +1 -1
  29. infrahub/core/protocols.py +4 -3
  30. infrahub/core/query/node.py +1 -1
  31. infrahub/core/query/relationship.py +2 -2
  32. infrahub/core/query/standard_node.py +19 -5
  33. infrahub/core/relationship/constraints/peer_relatives.py +72 -0
  34. infrahub/core/relationship/model.py +1 -1
  35. infrahub/core/schema/attribute_schema.py +26 -6
  36. infrahub/core/schema/basenode_schema.py +2 -2
  37. infrahub/core/schema/definitions/core/resource_pool.py +9 -0
  38. infrahub/core/schema/definitions/internal.py +9 -1
  39. infrahub/core/schema/generated/attribute_schema.py +4 -4
  40. infrahub/core/schema/generated/relationship_schema.py +6 -1
  41. infrahub/core/schema/manager.py +4 -2
  42. infrahub/core/schema/schema_branch.py +14 -5
  43. infrahub/core/validators/tasks.py +1 -1
  44. infrahub/database/__init__.py +1 -1
  45. infrahub/database/validation.py +100 -0
  46. infrahub/dependencies/builder/constraint/grouped/node_runner.py +2 -0
  47. infrahub/dependencies/builder/constraint/relationship_manager/peer_relatives.py +8 -0
  48. infrahub/dependencies/builder/diff/deserializer.py +1 -1
  49. infrahub/dependencies/registry.py +2 -0
  50. infrahub/events/models.py +1 -1
  51. infrahub/graphql/mutations/main.py +1 -1
  52. infrahub/graphql/mutations/resource_manager.py +13 -13
  53. infrahub/graphql/resolvers/many_relationship.py +1 -1
  54. infrahub/graphql/resolvers/resolver.py +2 -2
  55. infrahub/graphql/resolvers/single_relationship.py +1 -1
  56. infrahub/menu/menu.py +5 -4
  57. infrahub/message_bus/operations/refresh/registry.py +3 -3
  58. infrahub/patch/queries/delete_duplicated_edges.py +40 -29
  59. infrahub/pools/registration.py +22 -0
  60. infrahub/pools/tasks.py +56 -0
  61. infrahub/proposed_change/tasks.py +8 -8
  62. infrahub/schema/__init__.py +0 -0
  63. infrahub/schema/tasks.py +27 -0
  64. infrahub/schema/triggers.py +23 -0
  65. infrahub/trigger/catalogue.py +4 -0
  66. infrahub/trigger/models.py +5 -4
  67. infrahub/trigger/setup.py +26 -2
  68. infrahub/trigger/tasks.py +1 -1
  69. infrahub/webhook/tasks.py +6 -9
  70. infrahub/workflows/catalogue.py +27 -1
  71. {infrahub_server-1.3.0b1.dist-info → infrahub_server-1.3.0b3.dist-info}/METADATA +1 -1
  72. {infrahub_server-1.3.0b1.dist-info → infrahub_server-1.3.0b3.dist-info}/RECORD +80 -67
  73. infrahub_testcontainers/container.py +239 -64
  74. infrahub_testcontainers/docker-compose-cluster.test.yml +321 -0
  75. infrahub_testcontainers/docker-compose.test.yml +1 -0
  76. infrahub_testcontainers/helpers.py +15 -1
  77. infrahub_testcontainers/plugin.py +9 -0
  78. infrahub/patch/queries/consolidate_duplicated_nodes.py +0 -106
  79. {infrahub_server-1.3.0b1.dist-info → infrahub_server-1.3.0b3.dist-info}/LICENSE.txt +0 -0
  80. {infrahub_server-1.3.0b1.dist-info → infrahub_server-1.3.0b3.dist-info}/WHEEL +0 -0
  81. {infrahub_server-1.3.0b1.dist-info → infrahub_server-1.3.0b3.dist-info}/entry_points.txt +0 -0
@@ -15,7 +15,7 @@ from infrahub.events import BranchDeletedEvent
15
15
  from infrahub.git.repository import get_initialized_repo
16
16
  from infrahub.services import InfrahubServices # noqa: TC001 needed for prefect flow
17
17
  from infrahub.trigger.models import TriggerSetupReport, TriggerType
18
- from infrahub.trigger.setup import setup_triggers
18
+ from infrahub.trigger.setup import setup_triggers, setup_triggers_specific
19
19
  from infrahub.workflows.catalogue import (
20
20
  COMPUTED_ATTRIBUTE_PROCESS_JINJA2,
21
21
  COMPUTED_ATTRIBUTE_PROCESS_TRANSFORM,
@@ -304,36 +304,30 @@ async def computed_attribute_setup_jinja2(
304
304
  await add_tags(branches=[branch_name])
305
305
  await wait_for_schema_to_converge(branch_name=branch_name, component=service.component, db=db, log=log)
306
306
 
307
- triggers = await gather_trigger_computed_attribute_jinja2()
308
-
307
+ report: TriggerSetupReport = await setup_triggers_specific(
308
+ gatherer=gather_trigger_computed_attribute_jinja2, trigger_type=TriggerType.COMPUTED_ATTR_JINJA2
309
+ ) # type: ignore[misc]
309
310
  # Configure all ComputedAttrJinja2Trigger in Prefect
310
- async with get_client(sync_client=False) as prefect_client:
311
- report: TriggerSetupReport = await setup_triggers(
312
- client=prefect_client,
313
- triggers=triggers,
314
- trigger_type=TriggerType.COMPUTED_ATTR_JINJA2,
315
- force_update=False,
316
- ) # type: ignore[misc]
317
311
 
318
- # Since we can have multiple trigger per NodeKind
319
- # we need to extract the list of unique node that should be processed
320
- unique_nodes: set[tuple[str, str, str]] = {
321
- (trigger.branch, trigger.computed_attribute.kind, trigger.computed_attribute.attribute.name) # type: ignore[attr-defined]
322
- for trigger in report.updated + report.created
323
- }
324
- for branch, kind, attribute_name in unique_nodes:
325
- if event_name != BranchDeletedEvent.event_name and branch == branch_name:
326
- await service.workflow.submit_workflow(
327
- workflow=TRIGGER_UPDATE_JINJA_COMPUTED_ATTRIBUTES,
328
- context=context,
329
- parameters={
330
- "branch_name": branch,
331
- "computed_attribute_name": attribute_name,
332
- "computed_attribute_kind": kind,
333
- },
334
- )
335
-
336
- log.info(f"{len(triggers)} Computed Attribute for Jinja2 automation configuration completed")
312
+ # Since we can have multiple trigger per NodeKind
313
+ # we need to extract the list of unique node that should be processed
314
+ unique_nodes: set[tuple[str, str, str]] = {
315
+ (trigger.branch, trigger.computed_attribute.kind, trigger.computed_attribute.attribute.name) # type: ignore[attr-defined]
316
+ for trigger in report.updated + report.created
317
+ }
318
+ for branch, kind, attribute_name in unique_nodes:
319
+ if event_name != BranchDeletedEvent.event_name and branch == branch_name:
320
+ await service.workflow.submit_workflow(
321
+ workflow=TRIGGER_UPDATE_JINJA_COMPUTED_ATTRIBUTES,
322
+ context=context,
323
+ parameters={
324
+ "branch_name": branch,
325
+ "computed_attribute_name": attribute_name,
326
+ "computed_attribute_kind": kind,
327
+ },
328
+ )
329
+
330
+ log.info(f"{report.in_use_count} Computed Attribute for Jinja2 automation configuration completed")
337
331
 
338
332
 
339
333
  @flow(
@@ -112,6 +112,11 @@ class AccountType(InfrahubStringEnum):
112
112
  Git = "Git"
113
113
 
114
114
 
115
+ class NumberPoolType(InfrahubStringEnum):
116
+ USER = "User"
117
+ SCHEMA = "Schema"
118
+
119
+
115
120
  class AccountStatus(InfrahubStringEnum):
116
121
  ACTIVE = "active"
117
122
  INACTIVE = "inactive"
@@ -12,3 +12,4 @@ class DatabaseEdgeType(Enum):
12
12
  IS_PROTECTED = "IS_PROTECTED"
13
13
  HAS_OWNER = "HAS_OWNER"
14
14
  HAS_SOURCE = "HAS_SOURCE"
15
+ IS_RESERVED = "IS_RESERVED"
@@ -97,7 +97,7 @@ async def convert_object_type(
97
97
  if not isinstance(node_schema, NodeSchema):
98
98
  raise ValueError(f"Only a node with a NodeSchema can be converted, got {type(node_schema)}")
99
99
 
100
- async with db.start_transaction() as dbt: # noqa: PLR1702
100
+ async with db.start_transaction() as dbt:
101
101
  deleted_node_out_rels_peer_ids = await get_out_rels_peers_ids(node=node, db=dbt)
102
102
  deleted_node_unidir_rels_peer_ids = await get_unidirectional_rels_peers_ids(node=node, db=dbt, branch=branch)
103
103
 
@@ -78,6 +78,7 @@ class EnrichedNodeBatchCreateQuery(Query):
78
78
 
79
79
  async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
80
80
  self.params = self._build_node_batch_params()
81
+
81
82
  query = """
82
83
  UNWIND $node_details_list AS node_details
83
84
  WITH
@@ -131,57 +132,74 @@ CALL (diff_node, has_node_conflict, node_conflict_params) {
131
132
  OPTIONAL MATCH (diff_node)-[:DIFF_HAS_CONFLICT]->(node_conflict:DiffConflict)
132
133
  SET node_conflict = node_conflict_params
133
134
  }
135
+ // -------------------------
136
+ // resetting the UNWIND and starting over here reduces memory usage
137
+ // -------------------------
138
+ WITH root_uuid LIMIT 1
139
+ UNWIND $node_details_list AS node_details
140
+ WITH
141
+ node_details.root_uuid AS root_uuid,
142
+ node_details.node_map AS node_map,
143
+ toString(node_details.node_map.node_properties.uuid) AS node_uuid,
144
+ node_details.node_map.node_properties.db_id AS node_db_id
145
+ MATCH (:DiffRoot {uuid: root_uuid})-[:DIFF_HAS_NODE]->(diff_node:DiffNode {uuid: node_uuid, db_id: node_db_id})
146
+ WITH diff_node, node_map, %(attr_name_list_comp)s AS attr_names
147
+ OPTIONAL MATCH (diff_node)-[:DIFF_HAS_ATTRIBUTE]->(attr_to_delete:DiffAttribute)
148
+ WHERE NOT (attr_to_delete.name IN attr_names)
149
+ OPTIONAL MATCH (attr_to_delete)-[*..6]->(next_to_delete)
150
+ DETACH DELETE next_to_delete
151
+ DETACH DELETE attr_to_delete
152
+ // -------------------------
153
+ // add attributes for this node
154
+ // -------------------------
155
+ WITH DISTINCT diff_node, node_map
134
156
  CALL (diff_node, node_map) {
135
- // -------------------------
136
- // remove stale attributes for this node
137
- // -------------------------
138
- CALL (diff_node, node_map) {
139
- WITH %(attr_name_list_comp)s AS attr_names
140
- OPTIONAL MATCH (diff_node)-[:DIFF_HAS_ATTRIBUTE]->(attr_to_delete:DiffAttribute)
141
- WHERE NOT (attr_to_delete.name IN attr_names)
142
- OPTIONAL MATCH (attr_to_delete)-[*..6]->(next_to_delete)
143
- DETACH DELETE next_to_delete
144
- DETACH DELETE attr_to_delete
145
- }
146
- // -------------------------
147
- // add attributes for this node
148
- // -------------------------
149
157
  UNWIND node_map.attributes AS node_attribute
150
158
  MERGE (diff_node)-[:DIFF_HAS_ATTRIBUTE]->(diff_attribute:DiffAttribute {name: node_attribute.node_properties.name})
151
159
  SET diff_attribute = node_attribute.node_properties
152
160
  // -------------------------
153
- // add properties for this attribute
161
+ // remove stale properties for this attribute
154
162
  // -------------------------
155
- WITH diff_attribute, node_attribute
163
+ WITH diff_attribute, node_attribute, %(attr_props_list_comp)s AS prop_types
164
+ OPTIONAL MATCH (diff_attribute)-[:DIFF_HAS_PROPERTY]->(prop_to_delete:DiffProperty)
165
+ WHERE NOT (prop_to_delete.property_type IN prop_types)
166
+ OPTIONAL MATCH (prop_to_delete)-[*..4]->(next_to_delete)
167
+ DETACH DELETE next_to_delete
168
+ DETACH DELETE prop_to_delete
156
169
  // -------------------------
157
- // remove stale properties for this attribute
170
+ // set attribute property values
158
171
  // -------------------------
159
- CALL (diff_attribute, node_attribute) {
160
- WITH %(attr_props_list_comp)s AS prop_types
161
- OPTIONAL MATCH (diff_attribute)-[:DIFF_HAS_PROPERTY]->(prop_to_delete:DiffProperty)
162
- WHERE NOT (prop_to_delete.property_type IN prop_types)
163
- OPTIONAL MATCH (prop_to_delete)-[*..4]->(next_to_delete)
164
- DETACH DELETE next_to_delete
165
- DETACH DELETE prop_to_delete
166
- }
172
+ WITH DISTINCT diff_attribute, node_attribute
167
173
  UNWIND node_attribute.properties AS attr_property
168
174
  MERGE (diff_attribute)-[:DIFF_HAS_PROPERTY]->(diff_attr_prop:DiffProperty {property_type: attr_property.node_properties.property_type})
169
175
  SET diff_attr_prop = attr_property.node_properties
170
- // -------------------------
171
- // add/remove conflict for this property
172
- // -------------------------
173
176
  WITH diff_attr_prop, attr_property
174
177
  OPTIONAL MATCH (diff_attr_prop)-[:DIFF_HAS_CONFLICT]->(current_attr_prop_conflict:DiffConflict)
175
178
  WITH diff_attr_prop, attr_property, current_attr_prop_conflict, (attr_property.conflict_params IS NOT NULL) AS has_prop_conflict
176
- FOREACH (i in CASE WHEN has_prop_conflict = FALSE THEN [1] ELSE [] END |
179
+ CALL (has_prop_conflict, current_attr_prop_conflict) {
180
+ WITH has_prop_conflict, current_attr_prop_conflict
181
+ WHERE has_prop_conflict = FALSE AND current_attr_prop_conflict IS NOT NULL
177
182
  DETACH DELETE current_attr_prop_conflict
178
- )
179
- FOREACH (i in CASE WHEN has_prop_conflict = TRUE THEN [1] ELSE [] END |
183
+ }
184
+ CALL (has_prop_conflict, diff_attr_prop, attr_property) {
185
+ WITH has_prop_conflict
186
+ WHERE has_prop_conflict = TRUE
180
187
  MERGE (diff_attr_prop)-[:DIFF_HAS_CONFLICT]->(diff_attr_prop_conflict:DiffConflict)
181
188
  SET diff_attr_prop_conflict = attr_property.conflict_params
182
- )
189
+ }
183
190
  }
184
191
  // -------------------------
192
+ // resetting the UNWIND and starting over here reduces memory usage
193
+ // -------------------------
194
+ WITH 1 AS resetting LIMIT 1
195
+ UNWIND $node_details_list AS node_details
196
+ WITH
197
+ node_details.root_uuid AS root_uuid,
198
+ node_details.node_map AS node_map,
199
+ toString(node_details.node_map.node_properties.uuid) AS node_uuid,
200
+ node_details.node_map.node_properties.db_id AS node_db_id
201
+ MATCH (:DiffRoot {uuid: root_uuid})-[:DIFF_HAS_NODE]->(diff_node:DiffNode {uuid: node_uuid, db_id: node_db_id})
202
+ // -------------------------
185
203
  // remove stale relationships for this node
186
204
  // -------------------------
187
205
  CALL (diff_node, node_map) {
@@ -226,13 +244,17 @@ WITH diff_relationship_element, node_single_relationship
226
244
  OPTIONAL MATCH (diff_relationship_element)-[:DIFF_HAS_CONFLICT]->(current_element_conflict:DiffConflict)
227
245
  WITH diff_relationship_element, node_single_relationship, current_element_conflict,
228
246
  (node_single_relationship.conflict_params IS NOT NULL) AS has_element_conflict
229
- FOREACH (i in CASE WHEN has_element_conflict = FALSE THEN [1] ELSE [] END |
247
+ CALL (has_element_conflict, current_element_conflict) {
248
+ WITH has_element_conflict
249
+ WHERE has_element_conflict = FALSE
230
250
  DETACH DELETE current_element_conflict
231
- )
232
- FOREACH (i in CASE WHEN has_element_conflict = TRUE THEN [1] ELSE [] END |
251
+ }
252
+ CALL (has_element_conflict, diff_relationship_element, node_single_relationship) {
253
+ WITH has_element_conflict
254
+ WHERE has_element_conflict = TRUE
233
255
  MERGE (diff_relationship_element)-[:DIFF_HAS_CONFLICT]->(element_conflict:DiffConflict)
234
256
  SET element_conflict = node_single_relationship.conflict_params
235
- )
257
+ }
236
258
  // -------------------------
237
259
  // remove stale properties for this relationship element
238
260
  // -------------------------
@@ -260,13 +282,18 @@ WITH diff_relationship_property, node_relationship_property
260
282
  OPTIONAL MATCH (diff_relationship_property)-[:DIFF_HAS_CONFLICT]->(diff_relationship_property_conflict:DiffConflict)
261
283
  WITH diff_relationship_property, node_relationship_property, diff_relationship_property_conflict,
262
284
  (node_relationship_property.conflict_params IS NOT NULL) AS has_property_conflict
263
- FOREACH (i in CASE WHEN has_property_conflict = FALSE THEN [1] ELSE [] END |
285
+
286
+ CALL (has_property_conflict, diff_relationship_property_conflict) {
287
+ WITH has_property_conflict
288
+ WHERE has_property_conflict = FALSE
264
289
  DETACH DELETE diff_relationship_property_conflict
265
- )
266
- FOREACH (i in CASE WHEN has_property_conflict = TRUE THEN [1] ELSE [] END |
290
+ }
291
+ CALL (has_property_conflict, diff_relationship_property, node_relationship_property) {
292
+ WITH has_property_conflict
293
+ WHERE has_property_conflict = TRUE
267
294
  MERGE (diff_relationship_property)-[:DIFF_HAS_CONFLICT]->(property_conflict:DiffConflict)
268
295
  SET property_conflict = node_relationship_property.conflict_params
269
- )
296
+ }
270
297
  """ % {
271
298
  "attr_name_list_comp": db.render_list_comprehension(
272
299
  items="node_map.attributes", item_name="node_properties.name"
@@ -37,7 +37,6 @@ class EnrichedDiffTimeRangeQuery(Query):
37
37
  "from_time": self.from_time.to_string(),
38
38
  "to_time": self.to_time.to_string(),
39
39
  }
40
- # ruff: noqa: E501
41
40
  query = """
42
41
  // get the roots of all diffs in the query
43
42
  MATCH (diff_root:DiffRoot)
@@ -1 +1 @@
1
- GRAPH_VERSION = 28
1
+ GRAPH_VERSION = 30
@@ -29,6 +29,9 @@ from .m024_missing_hierarchy_backfill import Migration024
29
29
  from .m025_uniqueness_nulls import Migration025
30
30
  from .m026_0000_prefix_fix import Migration026
31
31
  from .m027_delete_isolated_nodes import Migration027
32
+ from .m028_delete_diffs import Migration028
33
+ from .m029_duplicates_cleanup import Migration029
34
+ from .m030_illegal_edges import Migration030
32
35
 
33
36
  if TYPE_CHECKING:
34
37
  from infrahub.core.root import Root
@@ -63,6 +66,9 @@ MIGRATIONS: list[type[GraphMigration | InternalSchemaMigration | ArbitraryMigrat
63
66
  Migration025,
64
67
  Migration026,
65
68
  Migration027,
69
+ Migration028,
70
+ Migration029,
71
+ Migration030,
66
72
  ]
67
73
 
68
74
 
@@ -77,7 +77,6 @@ class Migration013ConvertCoreRepositoryWithCred(Query):
77
77
 
78
78
  self.params["rel_identifier"] = "gitrepository__credential"
79
79
 
80
- # ruff: noqa: E501
81
80
  query = """
82
81
  // --------------------------------
83
82
  // Identify the git repositories to convert
@@ -194,7 +193,6 @@ class Migration013ConvertCoreRepositoryWithoutCred(Query):
194
193
 
195
194
  self.params["current_time"] = self.at.to_string()
196
195
 
197
- # ruff: noqa: E501
198
196
  query = """
199
197
  // --------------------------------
200
198
  // Identify the git repositories to convert