infrahub-server 1.1.6__py3-none-any.whl → 1.2.0rc0__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 (346) hide show
  1. infrahub/api/artifact.py +16 -4
  2. infrahub/api/dependencies.py +8 -0
  3. infrahub/api/oauth2.py +0 -1
  4. infrahub/api/oidc.py +0 -1
  5. infrahub/api/query.py +18 -7
  6. infrahub/api/schema.py +32 -6
  7. infrahub/api/transformation.py +12 -5
  8. infrahub/{message_bus/messages/check_artifact_create.py → artifacts/models.py} +2 -4
  9. infrahub/{message_bus/operations/check/artifact.py → artifacts/tasks.py} +26 -25
  10. infrahub/cli/__init__.py +0 -2
  11. infrahub/cli/db.py +6 -7
  12. infrahub/cli/events.py +8 -3
  13. infrahub/cli/git_agent.py +9 -7
  14. infrahub/cli/tasks.py +4 -6
  15. infrahub/computed_attribute/tasks.py +63 -17
  16. infrahub/computed_attribute/triggers.py +90 -0
  17. infrahub/config.py +1 -1
  18. infrahub/context.py +39 -0
  19. infrahub/core/account.py +5 -8
  20. infrahub/core/attribute.py +53 -21
  21. infrahub/core/branch/models.py +4 -4
  22. infrahub/core/branch/tasks.py +89 -130
  23. infrahub/core/changelog/__init__.py +0 -0
  24. infrahub/core/changelog/diff.py +232 -0
  25. infrahub/core/changelog/models.py +488 -0
  26. infrahub/core/constants/__init__.py +19 -2
  27. infrahub/core/constants/infrahubkind.py +1 -0
  28. infrahub/core/diff/combiner.py +12 -8
  29. infrahub/core/diff/coordinator.py +49 -70
  30. infrahub/core/diff/data_check_synchronizer.py +86 -7
  31. infrahub/core/diff/enricher/aggregated.py +3 -3
  32. infrahub/core/diff/enricher/cardinality_one.py +2 -7
  33. infrahub/core/diff/enricher/hierarchy.py +5 -3
  34. infrahub/core/diff/enricher/labels.py +14 -4
  35. infrahub/core/diff/enricher/path_identifier.py +3 -9
  36. infrahub/core/diff/enricher/summary_counts.py +3 -1
  37. infrahub/core/diff/merger/merger.py +8 -4
  38. infrahub/core/diff/model/path.py +47 -29
  39. infrahub/core/diff/query/all_conflicts.py +6 -3
  40. infrahub/core/diff/query/artifact.py +1 -1
  41. infrahub/core/diff/query/delete_query.py +1 -1
  42. infrahub/core/diff/query/diff_get.py +3 -2
  43. infrahub/core/diff/query/diff_summary.py +1 -1
  44. infrahub/core/diff/query/field_specifiers.py +3 -1
  45. infrahub/core/diff/query/field_summary.py +3 -2
  46. infrahub/core/diff/query/filters.py +12 -1
  47. infrahub/core/diff/query/get_conflict_query.py +1 -1
  48. infrahub/core/diff/query/has_conflicts_query.py +6 -3
  49. infrahub/core/diff/query/merge.py +3 -3
  50. infrahub/core/diff/query/{drop_tracking_id.py → merge_tracking_id.py} +4 -4
  51. infrahub/core/diff/query/roots_metadata.py +9 -2
  52. infrahub/core/diff/query/save.py +151 -66
  53. infrahub/core/diff/query/summary_counts_enricher.py +220 -0
  54. infrahub/core/diff/query/time_range_query.py +3 -2
  55. infrahub/core/diff/query/update_conflict_query.py +1 -1
  56. infrahub/core/diff/query_parser.py +49 -24
  57. infrahub/core/diff/repository/deserializer.py +24 -25
  58. infrahub/core/diff/repository/repository.py +76 -20
  59. infrahub/core/diff/tasks.py +9 -8
  60. infrahub/core/enums.py +1 -1
  61. infrahub/core/integrity/object_conflict/conflict_recorder.py +1 -1
  62. infrahub/core/ipam/reconciler.py +1 -1
  63. infrahub/core/ipam/tasks.py +2 -3
  64. infrahub/core/manager.py +18 -13
  65. infrahub/core/merge.py +5 -2
  66. infrahub/core/migrations/graph/m001_add_version_to_graph.py +1 -1
  67. infrahub/core/migrations/graph/m002_attribute_is_default.py +2 -2
  68. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +2 -2
  69. infrahub/core/migrations/graph/m004_add_attr_documentation.py +1 -1
  70. infrahub/core/migrations/graph/m005_add_rel_read_only.py +1 -1
  71. infrahub/core/migrations/graph/m006_add_rel_on_delete.py +1 -1
  72. infrahub/core/migrations/graph/m007_add_rel_allow_override.py +1 -1
  73. infrahub/core/migrations/graph/m008_add_human_friendly_id.py +1 -1
  74. infrahub/core/migrations/graph/m009_add_generate_profile_attr.py +1 -1
  75. infrahub/core/migrations/graph/m010_add_generate_profile_attr_generic.py +1 -1
  76. infrahub/core/migrations/graph/m011_remove_profile_relationship_schema.py +2 -2
  77. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -23
  78. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -11
  79. infrahub/core/migrations/graph/m014_remove_index_attr_value.py +2 -2
  80. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
  81. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
  82. infrahub/core/migrations/graph/m017_add_core_profile.py +1 -1
  83. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -2
  84. infrahub/core/migrations/query/attribute_add.py +1 -1
  85. infrahub/core/migrations/query/attribute_rename.py +1 -1
  86. infrahub/core/migrations/query/delete_element_in_schema.py +1 -1
  87. infrahub/core/migrations/query/node_duplicate.py +1 -1
  88. infrahub/core/migrations/query/relationship_duplicate.py +1 -1
  89. infrahub/core/migrations/query/schema_attribute_update.py +1 -1
  90. infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
  91. infrahub/core/migrations/schema/node_remove.py +1 -1
  92. infrahub/core/migrations/schema/tasks.py +5 -5
  93. infrahub/core/migrations/shared.py +4 -4
  94. infrahub/core/models.py +7 -8
  95. infrahub/core/node/__init__.py +161 -40
  96. infrahub/core/node/base.py +1 -1
  97. infrahub/core/node/constraints/grouped_uniqueness.py +9 -2
  98. infrahub/core/node/delete_validator.py +4 -4
  99. infrahub/core/node/ipam.py +13 -8
  100. infrahub/core/node/permissions.py +4 -0
  101. infrahub/core/node/resource_manager/ip_prefix_pool.py +8 -5
  102. infrahub/core/node/standard.py +3 -5
  103. infrahub/core/property.py +1 -1
  104. infrahub/core/protocols.py +4 -0
  105. infrahub/core/protocols_base.py +4 -2
  106. infrahub/core/query/__init__.py +2 -5
  107. infrahub/core/query/attribute.py +9 -9
  108. infrahub/core/query/branch.py +5 -5
  109. infrahub/core/query/delete.py +1 -1
  110. infrahub/core/query/diff.py +45 -7
  111. infrahub/core/query/ipam.py +4 -4
  112. infrahub/core/query/node.py +19 -14
  113. infrahub/core/query/relationship.py +10 -11
  114. infrahub/core/query/resource_manager.py +13 -11
  115. infrahub/core/query/standard_node.py +6 -6
  116. infrahub/core/query/task.py +3 -3
  117. infrahub/core/query/task_log.py +1 -1
  118. infrahub/core/query/utils.py +5 -5
  119. infrahub/core/registry.py +0 -2
  120. infrahub/core/relationship/constraints/count.py +1 -1
  121. infrahub/core/relationship/constraints/peer_kind.py +1 -1
  122. infrahub/core/relationship/model.py +66 -26
  123. infrahub/core/schema/__init__.py +6 -4
  124. infrahub/core/schema/basenode_schema.py +1 -3
  125. infrahub/core/schema/definitions/core.py +14 -2
  126. infrahub/core/schema/definitions/internal.py +16 -0
  127. infrahub/core/schema/generated/genericnode_schema.py +5 -0
  128. infrahub/core/schema/generated/node_schema.py +5 -0
  129. infrahub/core/schema/generic_schema.py +5 -1
  130. infrahub/core/schema/manager.py +45 -42
  131. infrahub/core/schema/node_schema.py +4 -0
  132. infrahub/core/schema/profile_schema.py +4 -0
  133. infrahub/core/schema/relationship_schema.py +2 -2
  134. infrahub/core/schema/schema_branch.py +248 -14
  135. infrahub/core/schema/template_schema.py +36 -0
  136. infrahub/core/task/user_task.py +7 -5
  137. infrahub/core/timestamp.py +1 -1
  138. infrahub/core/utils.py +3 -2
  139. infrahub/core/validators/attribute/choices.py +1 -1
  140. infrahub/core/validators/attribute/enum.py +1 -1
  141. infrahub/core/validators/attribute/kind.py +1 -1
  142. infrahub/core/validators/attribute/length.py +1 -1
  143. infrahub/core/validators/attribute/optional.py +1 -1
  144. infrahub/core/validators/attribute/regex.py +1 -1
  145. infrahub/core/validators/attribute/unique.py +1 -1
  146. infrahub/core/validators/checks_runner.py +37 -0
  147. infrahub/core/validators/node/generate_profile.py +1 -1
  148. infrahub/core/validators/node/hierarchy.py +1 -1
  149. infrahub/core/validators/query.py +1 -1
  150. infrahub/core/validators/relationship/count.py +1 -1
  151. infrahub/core/validators/relationship/optional.py +1 -1
  152. infrahub/core/validators/relationship/peer.py +1 -1
  153. infrahub/core/validators/tasks.py +8 -6
  154. infrahub/core/validators/uniqueness/query.py +20 -17
  155. infrahub/database/__init__.py +15 -2
  156. infrahub/database/memgraph.py +1 -1
  157. infrahub/dependencies/builder/constraint/grouped/node_runner.py +0 -2
  158. infrahub/dependencies/builder/diff/combiner.py +1 -1
  159. infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
  160. infrahub/dependencies/builder/diff/coordinator.py +0 -2
  161. infrahub/dependencies/builder/diff/deserializer.py +1 -1
  162. infrahub/dependencies/builder/diff/enricher/summary_counts.py +1 -1
  163. infrahub/events/branch_action.py +47 -21
  164. infrahub/events/group_action.py +73 -0
  165. infrahub/events/models.py +159 -51
  166. infrahub/events/node_action.py +74 -8
  167. infrahub/events/repository_action.py +8 -8
  168. infrahub/events/schema_action.py +21 -8
  169. infrahub/generators/tasks.py +12 -13
  170. infrahub/git/base.py +3 -5
  171. infrahub/git/constants.py +0 -1
  172. infrahub/git/integrator.py +36 -35
  173. infrahub/git/repository.py +7 -8
  174. infrahub/git/tasks.py +43 -107
  175. infrahub/git_credential/helper.py +2 -3
  176. infrahub/graphql/analyzer.py +572 -11
  177. infrahub/graphql/app.py +34 -26
  178. infrahub/graphql/auth/query_permission_checker/anonymous_checker.py +5 -5
  179. infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +4 -4
  180. infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +4 -4
  181. infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +28 -35
  182. infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -5
  183. infrahub/graphql/enums.py +1 -1
  184. infrahub/graphql/initialization.py +5 -1
  185. infrahub/graphql/loaders/node.py +2 -2
  186. infrahub/graphql/manager.py +59 -54
  187. infrahub/graphql/mutations/account.py +20 -13
  188. infrahub/graphql/mutations/artifact_definition.py +16 -12
  189. infrahub/graphql/mutations/branch.py +61 -40
  190. infrahub/graphql/mutations/computed_attribute.py +19 -13
  191. infrahub/graphql/mutations/diff.py +37 -9
  192. infrahub/graphql/mutations/diff_conflict.py +9 -8
  193. infrahub/graphql/mutations/graphql_query.py +19 -11
  194. infrahub/graphql/mutations/ipam.py +21 -19
  195. infrahub/graphql/mutations/main.py +197 -44
  196. infrahub/graphql/mutations/menu.py +8 -8
  197. infrahub/graphql/mutations/proposed_change.py +36 -28
  198. infrahub/graphql/mutations/relationship.py +302 -105
  199. infrahub/graphql/mutations/repository.py +41 -35
  200. infrahub/graphql/mutations/resource_manager.py +26 -26
  201. infrahub/graphql/mutations/schema.py +51 -33
  202. infrahub/graphql/mutations/tasks.py +16 -10
  203. infrahub/graphql/parser.py +1 -1
  204. infrahub/graphql/permissions.py +6 -4
  205. infrahub/graphql/queries/account.py +22 -18
  206. infrahub/graphql/queries/branch.py +6 -4
  207. infrahub/graphql/queries/diff/tree.py +48 -42
  208. infrahub/graphql/queries/event.py +112 -0
  209. infrahub/graphql/queries/internal.py +3 -3
  210. infrahub/graphql/queries/ipam.py +23 -18
  211. infrahub/graphql/queries/relationship.py +11 -10
  212. infrahub/graphql/queries/resource_manager.py +43 -27
  213. infrahub/graphql/queries/search.py +9 -8
  214. infrahub/graphql/queries/status.py +12 -9
  215. infrahub/graphql/queries/task.py +11 -9
  216. infrahub/graphql/resolvers/resolver.py +69 -43
  217. infrahub/graphql/resolvers/single_relationship.py +16 -10
  218. infrahub/graphql/schema.py +2 -0
  219. infrahub/graphql/subscription/__init__.py +1 -1
  220. infrahub/graphql/subscription/events.py +1 -1
  221. infrahub/graphql/subscription/graphql_query.py +8 -8
  222. infrahub/graphql/types/branch.py +2 -2
  223. infrahub/graphql/types/common.py +6 -1
  224. infrahub/graphql/types/enums.py +2 -0
  225. infrahub/graphql/types/event.py +100 -0
  226. infrahub/graphql/types/interface.py +2 -2
  227. infrahub/graphql/types/node.py +3 -3
  228. infrahub/graphql/types/permission.py +2 -2
  229. infrahub/graphql/types/relationship.py +3 -3
  230. infrahub/graphql/types/standard_node.py +9 -11
  231. infrahub/graphql/utils.py +28 -182
  232. infrahub/groups/tasks.py +2 -3
  233. infrahub/lock.py +1 -1
  234. infrahub/menu/constants.py +1 -0
  235. infrahub/menu/generator.py +14 -3
  236. infrahub/menu/menu.py +116 -127
  237. infrahub/menu/models.py +4 -4
  238. infrahub/message_bus/messages/__init__.py +0 -4
  239. infrahub/message_bus/messages/event_branch_merge.py +3 -0
  240. infrahub/message_bus/messages/request_proposedchange_pipeline.py +2 -0
  241. infrahub/message_bus/operations/__init__.py +3 -5
  242. infrahub/message_bus/operations/check/__init__.py +2 -2
  243. infrahub/message_bus/operations/check/generator.py +1 -3
  244. infrahub/message_bus/operations/check/repository.py +1 -1
  245. infrahub/message_bus/operations/event/branch.py +7 -3
  246. infrahub/message_bus/operations/event/schema.py +1 -1
  247. infrahub/message_bus/operations/finalize/validator.py +1 -1
  248. infrahub/message_bus/operations/git/file.py +2 -2
  249. infrahub/message_bus/operations/git/repository.py +1 -1
  250. infrahub/message_bus/operations/requests/__init__.py +0 -2
  251. infrahub/message_bus/operations/requests/generator_definition.py +1 -1
  252. infrahub/message_bus/operations/requests/proposed_change.py +26 -11
  253. infrahub/message_bus/operations/requests/repository.py +2 -2
  254. infrahub/message_bus/operations/send/echo.py +1 -1
  255. infrahub/message_bus/types.py +1 -1
  256. infrahub/permissions/__init__.py +2 -1
  257. infrahub/permissions/types.py +26 -0
  258. infrahub/pools/prefix.py +29 -165
  259. infrahub/prefect_server/__init__.py +0 -0
  260. infrahub/prefect_server/app.py +18 -0
  261. infrahub/prefect_server/database.py +20 -0
  262. infrahub/prefect_server/events.py +28 -0
  263. infrahub/prefect_server/models.py +46 -0
  264. infrahub/proposed_change/models.py +15 -1
  265. infrahub/proposed_change/tasks.py +173 -35
  266. infrahub/pytest_plugin.py +4 -4
  267. infrahub/server.py +12 -11
  268. infrahub/services/__init__.py +147 -62
  269. infrahub/services/adapters/cache/__init__.py +7 -5
  270. infrahub/services/adapters/cache/nats.py +40 -22
  271. infrahub/services/adapters/cache/redis.py +0 -4
  272. infrahub/services/adapters/event/__init__.py +10 -18
  273. infrahub/services/adapters/http/__init__.py +0 -5
  274. infrahub/services/adapters/http/httpx.py +22 -15
  275. infrahub/services/adapters/message_bus/__init__.py +23 -6
  276. infrahub/services/adapters/message_bus/local.py +8 -6
  277. infrahub/services/adapters/message_bus/nats.py +12 -6
  278. infrahub/services/adapters/message_bus/rabbitmq.py +22 -9
  279. infrahub/services/adapters/workflow/__init__.py +11 -8
  280. infrahub/services/adapters/workflow/local.py +28 -7
  281. infrahub/services/adapters/workflow/worker.py +23 -7
  282. infrahub/services/component.py +38 -35
  283. infrahub/services/scheduler.py +32 -29
  284. infrahub/storage.py +2 -4
  285. infrahub/task_manager/constants.py +1 -1
  286. infrahub/task_manager/event.py +182 -0
  287. infrahub/task_manager/models.py +125 -1
  288. infrahub/task_manager/task.py +1 -1
  289. infrahub/tasks/artifact.py +14 -16
  290. infrahub/tasks/registry.py +1 -1
  291. infrahub/tasks/telemetry.py +13 -14
  292. infrahub/transformations/tasks.py +3 -5
  293. infrahub/trigger/__init__.py +0 -0
  294. infrahub/trigger/catalogue.py +15 -0
  295. infrahub/trigger/constants.py +9 -0
  296. infrahub/trigger/models.py +69 -0
  297. infrahub/trigger/tasks.py +85 -0
  298. infrahub/types.py +1 -1
  299. infrahub/utils.py +1 -1
  300. infrahub/webhook/constants.py +0 -2
  301. infrahub/webhook/models.py +8 -2
  302. infrahub/webhook/tasks.py +20 -73
  303. infrahub/webhook/triggers.py +20 -0
  304. infrahub/workers/infrahub_async.py +36 -25
  305. infrahub/workers/utils.py +63 -0
  306. infrahub/workflows/catalogue.py +13 -37
  307. infrahub/workflows/initialization.py +6 -8
  308. infrahub/workflows/models.py +3 -5
  309. infrahub/workflows/utils.py +1 -1
  310. infrahub_sdk/ctl/check.py +3 -3
  311. infrahub_sdk/ctl/cli_commands.py +11 -10
  312. infrahub_sdk/ctl/exceptions.py +0 -6
  313. infrahub_sdk/ctl/exporter.py +1 -1
  314. infrahub_sdk/ctl/generator.py +5 -5
  315. infrahub_sdk/ctl/importer.py +3 -2
  316. infrahub_sdk/ctl/menu.py +1 -1
  317. infrahub_sdk/ctl/object.py +1 -1
  318. infrahub_sdk/ctl/repository.py +23 -15
  319. infrahub_sdk/ctl/schema.py +2 -2
  320. infrahub_sdk/ctl/utils.py +4 -3
  321. infrahub_sdk/ctl/validate.py +2 -1
  322. infrahub_sdk/exceptions.py +6 -0
  323. infrahub_sdk/generator.py +3 -0
  324. infrahub_sdk/node.py +2 -2
  325. infrahub_sdk/schema/__init__.py +14 -2
  326. infrahub_sdk/schema/main.py +7 -0
  327. infrahub_sdk/utils.py +11 -1
  328. infrahub_sdk/yaml.py +2 -3
  329. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/METADATA +46 -12
  330. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/RECORD +338 -321
  331. infrahub_testcontainers/container.py +14 -6
  332. infrahub_testcontainers/docker-compose.test.yml +24 -5
  333. infrahub_testcontainers/haproxy.cfg +43 -0
  334. infrahub_testcontainers/helpers.py +85 -1
  335. infrahub/core/branch/constants.py +0 -2
  336. infrahub/graphql/query.py +0 -52
  337. infrahub/message_bus/messages/request_artifactdefinition_check.py +0 -17
  338. infrahub/message_bus/operations/requests/artifact_definition.py +0 -148
  339. infrahub/schema/constants.py +0 -1
  340. infrahub/schema/tasks.py +0 -76
  341. infrahub/services/adapters/database/__init__.py +0 -9
  342. infrahub_sdk/ctl/_file.py +0 -13
  343. /infrahub/{schema → artifacts}/__init__.py +0 -0
  344. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/LICENSE.txt +0 -0
  345. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/WHEEL +0 -0
  346. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/entry_points.txt +0 -0
@@ -1,9 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- from dataclasses import asdict, dataclass, field, replace
3
+ from dataclasses import asdict, dataclass, field
4
4
  from enum import Enum
5
5
  from typing import TYPE_CHECKING, Any, Optional
6
- from uuid import uuid4
7
6
 
8
7
  from infrahub.core.constants import (
9
8
  BranchSupportType,
@@ -171,6 +170,12 @@ class EnrichedDiffAttribute(BaseSummary):
171
170
  for prop in self.properties:
172
171
  prop.conflict = None
173
172
 
173
+ def get_property(self, property_type: DatabaseEdgeType) -> EnrichedDiffProperty:
174
+ for prop in self.properties:
175
+ if prop.property_type is property_type:
176
+ return prop
177
+ raise ValueError(f"No {property_type.value} property found")
178
+
174
179
  @classmethod
175
180
  def from_calculated_attribute(cls, calculated_attribute: DiffAttribute) -> EnrichedDiffAttribute:
176
181
  return EnrichedDiffAttribute(
@@ -253,6 +258,12 @@ class EnrichedDiffRelationship(BaseSummary):
253
258
  for element in self.relationships:
254
259
  element.clear_conflicts()
255
260
 
261
+ def get_element(self, peer_id: str) -> EnrichedDiffSingleRelationship:
262
+ for element in self.relationships:
263
+ if element.peer_id == peer_id:
264
+ return element
265
+ raise ValueError(f"No relationship for {peer_id} found")
266
+
256
267
  @property
257
268
  def include_in_response(self) -> bool:
258
269
  if self.action == DiffAction.UNCHANGED and not self.relationships:
@@ -314,18 +325,18 @@ class EnrichedDiffNode(BaseSummary):
314
325
  rel.clear_conflicts()
315
326
  self.conflict = None
316
327
 
317
- def get_parent_info(self, context: GraphqlContext | None = None) -> ParentNodeInfo | None:
328
+ def get_parent_info(self, graphql_context: GraphqlContext | None = None) -> ParentNodeInfo | None:
318
329
  for r in self.relationships:
319
330
  for n in r.nodes:
320
331
  relationship_name: str = "undefined"
321
332
 
322
- if not context:
333
+ if not graphql_context:
323
334
  return ParentNodeInfo(node=n, relationship_name=relationship_name)
324
335
 
325
- node_schema = context.db.schema.get(name=self.kind)
336
+ node_schema = graphql_context.db.schema.get(name=self.kind)
326
337
  rel_schema = node_schema.get_relationship(name=r.name)
327
338
 
328
- parent_schema = context.db.schema.get(name=n.kind)
339
+ parent_schema = graphql_context.db.schema.get(name=n.kind)
329
340
  rels_parent = parent_schema.get_relationships_by_identifier(id=rel_schema.get_identifier())
330
341
 
331
342
  if rels_parent and len(rels_parent) == 1:
@@ -353,16 +364,11 @@ class EnrichedDiffNode(BaseSummary):
353
364
  all_children |= n.get_all_child_nodes()
354
365
  return all_children
355
366
 
356
- def get_trimmed_node(self, max_depth: int) -> EnrichedDiffNode:
357
- trimmed = replace(self, relationships=set())
358
- for rel in self.relationships:
359
- trimmed_rel = replace(rel, nodes=set())
360
- trimmed.relationships.add(trimmed_rel)
361
- if max_depth == 0:
362
- continue
363
- for child_node in rel.nodes:
364
- trimmed_rel.nodes.add(child_node.get_trimmed_node(max_depth=max_depth - 1))
365
- return trimmed
367
+ def get_attribute(self, name: str) -> EnrichedDiffAttribute:
368
+ for attr in self.attributes:
369
+ if attr.name == name:
370
+ return attr
371
+ raise ValueError(f"No attribute {name} found")
366
372
 
367
373
  def get_relationship(self, name: str) -> EnrichedDiffRelationship:
368
374
  for rel in self.relationships:
@@ -404,7 +410,8 @@ class EnrichedDiffRootMetadata(BaseSummary):
404
410
  to_time: Timestamp
405
411
  uuid: str
406
412
  partner_uuid: str
407
- tracking_id: TrackingId | None = field(default=None, kw_only=True)
413
+ tracking_id: TrackingId
414
+ exists_on_database: bool = field(default=False)
408
415
 
409
416
  def __hash__(self) -> int:
410
417
  return hash(self.uuid)
@@ -426,7 +433,7 @@ class EnrichedDiffRootMetadata(BaseSummary):
426
433
  if to_time and self.to_time != to_time:
427
434
  self.to_time = to_time
428
435
  is_changed = True
429
- if self.tracking_id != tracking_id:
436
+ if self.tracking_id != tracking_id and tracking_id is not None:
430
437
  self.tracking_id = tracking_id
431
438
  is_changed = True
432
439
  return is_changed
@@ -475,7 +482,11 @@ class EnrichedDiffRoot(EnrichedDiffRootMetadata):
475
482
 
476
483
  @classmethod
477
484
  def from_calculated_diff(
478
- cls, calculated_diff: DiffRoot, base_branch_name: str, partner_uuid: str
485
+ cls,
486
+ calculated_diff: DiffRoot,
487
+ base_branch_name: str,
488
+ partner_uuid: str,
489
+ tracking_id: TrackingId,
479
490
  ) -> EnrichedDiffRoot:
480
491
  return EnrichedDiffRoot(
481
492
  base_branch_name=base_branch_name,
@@ -484,6 +495,7 @@ class EnrichedDiffRoot(EnrichedDiffRootMetadata):
484
495
  to_time=calculated_diff.to_time,
485
496
  uuid=calculated_diff.uuid,
486
497
  partner_uuid=partner_uuid,
498
+ tracking_id=tracking_id,
487
499
  nodes={EnrichedDiffNode.from_calculated_node(calculated_node=n) for n in calculated_diff.nodes},
488
500
  )
489
501
 
@@ -563,14 +575,6 @@ class EnrichedDiffsMetadata:
563
575
  )
564
576
  return is_changed
565
577
 
566
- def set_fresh_uuids(self) -> None:
567
- base_uuid = str(uuid4())
568
- branch_uuid = str(uuid4())
569
- self.base_branch_diff.uuid = base_uuid
570
- self.base_branch_diff.partner_uuid = branch_uuid
571
- self.diff_branch_diff.uuid = branch_uuid
572
- self.diff_branch_diff.partner_uuid = base_uuid
573
-
574
578
 
575
579
  @dataclass
576
580
  class EnrichedDiffs(EnrichedDiffsMetadata):
@@ -591,16 +595,18 @@ class EnrichedDiffs(EnrichedDiffsMetadata):
591
595
  )
592
596
 
593
597
  @classmethod
594
- def from_calculated_diffs(cls, calculated_diffs: CalculatedDiffs) -> EnrichedDiffs:
598
+ def from_calculated_diffs(cls, calculated_diffs: CalculatedDiffs, tracking_id: TrackingId) -> EnrichedDiffs:
595
599
  base_branch_diff = EnrichedDiffRoot.from_calculated_diff(
596
600
  calculated_diff=calculated_diffs.base_branch_diff,
597
601
  base_branch_name=calculated_diffs.base_branch_name,
598
602
  partner_uuid=calculated_diffs.diff_branch_diff.uuid,
603
+ tracking_id=tracking_id,
599
604
  )
600
605
  diff_branch_diff = EnrichedDiffRoot.from_calculated_diff(
601
606
  calculated_diff=calculated_diffs.diff_branch_diff,
602
607
  base_branch_name=calculated_diffs.base_branch_name,
603
608
  partner_uuid=calculated_diffs.base_branch_diff.uuid,
609
+ tracking_id=tracking_id,
604
610
  )
605
611
  return EnrichedDiffs(
606
612
  base_branch_name=calculated_diffs.base_branch_name,
@@ -613,6 +619,14 @@ class EnrichedDiffs(EnrichedDiffsMetadata):
613
619
  def is_empty(self) -> bool:
614
620
  return len(self.base_branch_diff.nodes) == 0 and len(self.diff_branch_diff.nodes) == 0
615
621
 
622
+ @property
623
+ def base_node_uuids(self) -> set[str]:
624
+ return {n.uuid for n in self.base_branch_diff.nodes}
625
+
626
+ @property
627
+ def branch_node_uuids(self) -> set[str]:
628
+ return {n.uuid for n in self.diff_branch_diff.nodes}
629
+
616
630
 
617
631
  @dataclass
618
632
  class CalculatedDiffs:
@@ -678,7 +692,7 @@ class DiffRoot:
678
692
 
679
693
 
680
694
  @dataclass
681
- class DatabasePath: # pylint: disable=too-many-public-methods
695
+ class DatabasePath:
682
696
  root_node: Neo4jNode
683
697
  path_to_node: Neo4jRelationship
684
698
  node_node: Neo4jNode
@@ -739,6 +753,10 @@ class DatabasePath: # pylint: disable=too-many-public-methods
739
753
  def node_id(self) -> str:
740
754
  return str(self.node_node.get("uuid"))
741
755
 
756
+ @property
757
+ def node_db_id(self) -> str:
758
+ return self.node_node.element_id
759
+
742
760
  @property
743
761
  def node_kind(self) -> str:
744
762
  return str(self.node_node.get("kind"))
@@ -24,7 +24,7 @@ class EnrichedDiffAllConflictsQuery(Query):
24
24
  if self.tracking_id is None and self.diff_id is None:
25
25
  raise RuntimeError("tracking_id or diff_id is required")
26
26
 
27
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
27
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
28
28
  self.params = {
29
29
  "diff_branch_name": self.diff_branch_name,
30
30
  "diff_id": self.diff_id,
@@ -32,8 +32,11 @@ class EnrichedDiffAllConflictsQuery(Query):
32
32
  }
33
33
  query = """
34
34
  MATCH (root:DiffRoot)
35
- WHERE ($diff_id IS NOT NULL AND root.uuid = $diff_id)
36
- OR ($tracking_id IS NOT NULL AND root.tracking_id = $tracking_id AND root.diff_branch = $diff_branch_name)
35
+ WHERE (root.is_merged IS NULL OR root.is_merged <> TRUE)
36
+ AND (
37
+ ($diff_id IS NOT NULL AND root.uuid = $diff_id)
38
+ OR ($tracking_id IS NOT NULL AND root.tracking_id = $tracking_id AND root.diff_branch = $diff_branch_name)
39
+ )
37
40
  CALL {
38
41
  WITH root
39
42
  MATCH (root)-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_CONFLICT]->(node_conflict:DiffConflict)
@@ -22,7 +22,7 @@ class ArtifactDiffQuery(Query):
22
22
  self.target_rel_identifier = target_rel_identifier
23
23
  self.definition_rel_identifier = definition_rel_identifier
24
24
 
25
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
25
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
26
26
  source_branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
27
27
  self.params.update(branch_params)
28
28
 
@@ -13,7 +13,7 @@ class EnrichedDiffDeleteQuery(Query):
13
13
  super().__init__(**kwargs)
14
14
  self.enriched_diff_root_uuids = enriched_diff_root_uuids
15
15
 
16
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
16
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
17
17
  self.params = {"diff_root_uuids": self.enriched_diff_root_uuids}
18
18
  query = """
19
19
  MATCH (d_root:DiffRoot)
@@ -11,7 +11,8 @@ from .filters import EnrichedDiffQueryFilters
11
11
  QUERY_MATCH_NODES = """
12
12
  // get the roots of all diffs in the query
13
13
  MATCH (diff_root:DiffRoot)
14
- WHERE diff_root.base_branch = $base_branch
14
+ WHERE (diff_root.is_merged IS NULL OR diff_root.is_merged <> TRUE)
15
+ AND diff_root.base_branch = $base_branch
15
16
  AND diff_root.diff_branch IN $diff_branches
16
17
  AND ($from_time IS NULL OR diff_root.from_time >= $from_time)
17
18
  AND ($to_time IS NULL OR diff_root.to_time <= $to_time)
@@ -51,7 +52,7 @@ class EnrichedDiffGetQuery(Query):
51
52
  self.diff_ids = diff_ids
52
53
  self.filters = filters or EnrichedDiffQueryFilters()
53
54
 
54
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
55
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
55
56
  self.params = {
56
57
  "base_branch": self.base_branch_name,
57
58
  "diff_branches": self.diff_branch_names,
@@ -61,7 +61,7 @@ class DiffSummaryQuery(Query):
61
61
  self.to_time = to_time
62
62
  self.tracking_id = tracking_id
63
63
 
64
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
64
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
65
65
  if (self.from_time is None or self.to_time is None) and self.tracking_id is None:
66
66
  raise ValueError("DiffSummaryQuery requires from_time and to_time or tracking_id ")
67
67
  self.params = {
@@ -12,14 +12,16 @@ class EnrichedDiffFieldSpecifiersQuery(Query):
12
12
  super().__init__(**kwargs)
13
13
  self.diff_id = diff_id
14
14
 
15
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
15
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
16
16
  self.params["diff_id"] = self.diff_id
17
17
  query = """
18
18
  CALL {
19
19
  MATCH (root:DiffRoot {uuid: $diff_id})-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_ATTRIBUTE]->(attr:DiffAttribute)
20
+ WHERE (root.is_merged IS NULL OR root.is_merged <> TRUE)
20
21
  RETURN node.uuid AS node_uuid, attr.name AS field_name
21
22
  UNION
22
23
  MATCH (root:DiffRoot {uuid: $diff_id})-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_RELATIONSHIP]->(rel:DiffRelationship)
24
+ WHERE (root.is_merged IS NULL OR root.is_merged <> TRUE)
23
25
  RETURN node.uuid AS node_uuid, rel.identifier AS field_name
24
26
  }
25
27
  """
@@ -27,7 +27,7 @@ class EnrichedDiffNodeFieldSummaryQuery(Query):
27
27
  self.tracking_id = tracking_id
28
28
  self.diff_id = diff_id
29
29
 
30
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
30
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
31
31
  if self.tracking_id is None and self.diff_id is None:
32
32
  raise RuntimeError("Either tacking_id or diff_id is required")
33
33
  self.params = {
@@ -38,7 +38,8 @@ class EnrichedDiffNodeFieldSummaryQuery(Query):
38
38
  }
39
39
  query = """
40
40
  MATCH (diff_root:DiffRoot)
41
- WHERE diff_root.diff_branch = $diff_branch
41
+ WHERE (diff_root.is_merged IS NULL OR diff_root.is_merged <> TRUE)
42
+ AND diff_root.diff_branch = $diff_branch
42
43
  AND (diff_root.tracking_id = $tracking_id OR $tracking_id IS NULL)
43
44
  AND (diff_root.uuid = $diff_id OR $diff_id IS NULL)
44
45
  OPTIONAL MATCH (diff_root)-[:DIFF_HAS_NODE]->(n:DiffNode)
@@ -31,10 +31,17 @@ class EnrichedDiffQueryFilters(BaseModel):
31
31
  kind: IncExclFilterOptions = IncExclFilterOptions()
32
32
  namespace: IncExclFilterOptions = IncExclFilterOptions()
33
33
  status: IncExclActionFilterOptions = IncExclActionFilterOptions()
34
+ only_conflicted: bool = Field(default=False)
34
35
 
35
36
  @property
36
37
  def is_empty(self) -> bool:
37
- if not self.ids and self.kind.is_empty and self.namespace.is_empty and self.status.is_empty:
38
+ if (
39
+ not self.ids
40
+ and self.only_conflicted is False
41
+ and self.kind.is_empty
42
+ and self.namespace.is_empty
43
+ and self.status.is_empty
44
+ ):
38
45
  return True
39
46
  return False
40
47
 
@@ -91,4 +98,8 @@ class EnrichedDiffQueryFilters(BaseModel):
91
98
 
92
99
  filters_list.append(filter_and(filter_action))
93
100
 
101
+ # ONLY NODES WITH CONFLICTS
102
+ if self.only_conflicted is True:
103
+ filters_list.append("diff_node.contains_conflict = TRUE")
104
+
94
105
  return filter_and(filters_list), params
@@ -14,7 +14,7 @@ class EnrichedDiffConflictQuery(Query):
14
14
  super().__init__(**kwargs)
15
15
  self.conflict_id = conflict_id
16
16
 
17
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
17
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
18
18
  self.params = {"conflict_id": self.conflict_id}
19
19
  query = "MATCH (conflict:DiffConflict {uuid: $conflict_id})"
20
20
  self.return_labels = ["conflict"]
@@ -25,7 +25,7 @@ class EnrichedDiffHasConflictQuery(Query):
25
25
  self.tracking_id = tracking_id
26
26
  self.diff_id = diff_id
27
27
 
28
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
28
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
29
29
  self.params = {
30
30
  "diff_branch_name": self.diff_branch_name,
31
31
  "tracking_id": self.tracking_id.serialize() if self.tracking_id else None,
@@ -33,8 +33,11 @@ class EnrichedDiffHasConflictQuery(Query):
33
33
  }
34
34
  query = """
35
35
  MATCH (diff_root:DiffRoot)
36
- WHERE ($diff_id IS NOT NULL AND diff_root.uuid = $diff_id)
37
- OR ($tracking_id IS NOT NULL AND diff_root.tracking_id = $tracking_id AND diff_root.diff_branch = $diff_branch_name)
36
+ WHERE (diff_root.is_merged IS NULL OR diff_root.is_merged <> TRUE)
37
+ AND (
38
+ ($diff_id IS NOT NULL AND diff_root.uuid = $diff_id)
39
+ OR ($tracking_id IS NOT NULL AND diff_root.tracking_id = $tracking_id AND diff_root.diff_branch = $diff_branch_name)
40
+ )
38
41
  WITH (
39
42
  exists(
40
43
  (diff_root)-[:DIFF_HAS_NODE]->(:DiffNode)-[:DIFF_HAS_CONFLICT]->(:DiffConflict)
@@ -28,7 +28,7 @@ class DiffMergeQuery(Query):
28
28
  self.target_branch = target_branch
29
29
  self.source_branch_name = self.branch.name
30
30
 
31
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
31
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
32
32
  self.params = {
33
33
  "node_diff_dicts": self.node_diff_dicts,
34
34
  "at": self.at.to_string(),
@@ -339,7 +339,7 @@ class DiffMergePropertiesQuery(Query):
339
339
  self.target_branch = target_branch
340
340
  self.source_branch_name = self.branch.name
341
341
 
342
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
342
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
343
343
  self.params = {
344
344
  "property_diff_dicts": self.property_diff_dicts,
345
345
  "at": self.at.to_string(),
@@ -514,7 +514,7 @@ class DiffMergeRollbackQuery(Query):
514
514
  self.target_branch = target_branch
515
515
  self.source_branch_name = self.branch.name
516
516
 
517
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
517
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
518
518
  self.params = {
519
519
  "at": self.at.to_string(),
520
520
  "target_branch": self.target_branch.name,
@@ -6,8 +6,8 @@ from infrahub.database import InfrahubDatabase
6
6
  from ..model.path import TrackingId
7
7
 
8
8
 
9
- class EnrichedDiffDropTrackingIdQuery(Query):
10
- name = "enriched_diff_drop_tracking_id"
9
+ class EnrichedDiffMergedTrackingIdQuery(Query):
10
+ name = "enriched_diff_merge_tracking_id"
11
11
  type = QueryType.WRITE
12
12
  insert_return = False
13
13
 
@@ -15,11 +15,11 @@ class EnrichedDiffDropTrackingIdQuery(Query):
15
15
  super().__init__(**kwargs)
16
16
  self.tracking_ids = tracking_ids
17
17
 
18
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
18
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
19
19
  self.params = {"tracking_ids": [t_id.serialize() for t_id in self.tracking_ids]}
20
20
  query = """
21
21
  MATCH (d_root:DiffRoot)
22
22
  WHERE d_root.tracking_id IN $tracking_ids
23
- SET d_root.tracking_id = NULL
23
+ SET d_root.is_merged = TRUE
24
24
  """
25
25
  self.add_to_query(query=query)
@@ -6,6 +6,8 @@ from infrahub.core.query import Query, QueryType
6
6
  from infrahub.core.timestamp import Timestamp
7
7
  from infrahub.database import InfrahubDatabase
8
8
 
9
+ from ..model.path import TrackingId
10
+
9
11
 
10
12
  class EnrichedDiffRootsMetadataQuery(Query):
11
13
  name = "enriched_diff_roots_metadata"
@@ -17,6 +19,7 @@ class EnrichedDiffRootsMetadataQuery(Query):
17
19
  base_branch_names: list[str] | None = None,
18
20
  from_time: Timestamp | None = None,
19
21
  to_time: Timestamp | None = None,
22
+ tracking_id: TrackingId | None = None,
20
23
  **kwargs: Any,
21
24
  ) -> None:
22
25
  super().__init__(**kwargs)
@@ -24,21 +27,25 @@ class EnrichedDiffRootsMetadataQuery(Query):
24
27
  self.base_branch_names = base_branch_names
25
28
  self.from_time = from_time
26
29
  self.to_time = to_time
30
+ self.tracking_id = tracking_id
27
31
 
28
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
32
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
29
33
  self.params = {
30
34
  "diff_branch_names": self.diff_branch_names,
31
35
  "base_branch_names": self.base_branch_names,
32
36
  "from_time": self.from_time.to_string() if self.from_time else None,
33
37
  "to_time": self.to_time.to_string() if self.to_time else None,
38
+ "tracking_id": self.tracking_id.serialize() if self.tracking_id else None,
34
39
  }
35
40
 
36
41
  query = """
37
42
  MATCH (diff_root:DiffRoot)
38
- WHERE ($diff_branch_names IS NULL OR diff_root.diff_branch IN $diff_branch_names)
43
+ WHERE (diff_root.is_merged IS NULL OR diff_root.is_merged <> TRUE)
44
+ AND ($diff_branch_names IS NULL OR diff_root.diff_branch IN $diff_branch_names)
39
45
  AND ($base_branch_names IS NULL OR diff_root.base_branch IN $base_branch_names)
40
46
  AND ($from_time IS NULL OR diff_root.from_time >= $from_time)
41
47
  AND ($to_time IS NULL OR diff_root.to_time <= $to_time)
48
+ AND ($tracking_id IS NULL OR diff_root.tracking_id = $tracking_id)
42
49
  """
43
50
  self.return_labels = ["diff_root"]
44
51
  self.add_to_query(query=query)