infrahub-server 1.1.6__py3-none-any.whl → 1.2.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 (407) 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} +5 -3
  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/models.py +1 -1
  16. infrahub/computed_attribute/tasks.py +64 -17
  17. infrahub/computed_attribute/triggers.py +90 -0
  18. infrahub/config.py +1 -1
  19. infrahub/context.py +39 -0
  20. infrahub/core/account.py +5 -8
  21. infrahub/core/attribute.py +54 -22
  22. infrahub/core/branch/models.py +4 -4
  23. infrahub/core/branch/tasks.py +137 -129
  24. infrahub/core/changelog/__init__.py +0 -0
  25. infrahub/core/changelog/diff.py +283 -0
  26. infrahub/core/changelog/models.py +499 -0
  27. infrahub/core/constants/__init__.py +43 -2
  28. infrahub/core/constants/infrahubkind.py +1 -0
  29. infrahub/core/constants/schema.py +2 -0
  30. infrahub/core/diff/combiner.py +12 -8
  31. infrahub/core/diff/coordinator.py +49 -70
  32. infrahub/core/diff/data_check_synchronizer.py +86 -7
  33. infrahub/core/diff/enricher/aggregated.py +3 -3
  34. infrahub/core/diff/enricher/cardinality_one.py +7 -7
  35. infrahub/core/diff/enricher/hierarchy.py +22 -7
  36. infrahub/core/diff/enricher/labels.py +19 -4
  37. infrahub/core/diff/enricher/path_identifier.py +7 -9
  38. infrahub/core/diff/enricher/summary_counts.py +3 -1
  39. infrahub/core/diff/merger/merger.py +8 -4
  40. infrahub/core/diff/model/path.py +76 -35
  41. infrahub/core/diff/parent_node_adder.py +78 -0
  42. infrahub/core/diff/payload_builder.py +13 -2
  43. infrahub/core/diff/query/all_conflicts.py +6 -3
  44. infrahub/core/diff/query/artifact.py +1 -1
  45. infrahub/core/diff/query/delete_query.py +1 -1
  46. infrahub/core/diff/query/diff_get.py +3 -2
  47. infrahub/core/diff/query/diff_summary.py +1 -1
  48. infrahub/core/diff/query/field_specifiers.py +3 -1
  49. infrahub/core/diff/query/field_summary.py +3 -2
  50. infrahub/core/diff/query/filters.py +14 -3
  51. infrahub/core/diff/query/get_conflict_query.py +1 -1
  52. infrahub/core/diff/query/has_conflicts_query.py +6 -3
  53. infrahub/core/diff/query/merge.py +3 -3
  54. infrahub/core/diff/query/{drop_tracking_id.py → merge_tracking_id.py} +4 -4
  55. infrahub/core/diff/query/roots_metadata.py +9 -2
  56. infrahub/core/diff/query/save.py +233 -142
  57. infrahub/core/diff/query/summary_counts_enricher.py +267 -0
  58. infrahub/core/diff/query/time_range_query.py +3 -2
  59. infrahub/core/diff/query/update_conflict_query.py +1 -1
  60. infrahub/core/diff/query_parser.py +49 -24
  61. infrahub/core/diff/repository/deserializer.py +32 -28
  62. infrahub/core/diff/repository/repository.py +215 -41
  63. infrahub/core/diff/tasks.py +13 -12
  64. infrahub/core/enums.py +1 -1
  65. infrahub/core/graph/__init__.py +1 -1
  66. infrahub/core/graph/index.py +3 -0
  67. infrahub/core/integrity/object_conflict/conflict_recorder.py +1 -1
  68. infrahub/core/ipam/reconciler.py +1 -1
  69. infrahub/core/ipam/tasks.py +2 -3
  70. infrahub/core/manager.py +20 -15
  71. infrahub/core/merge.py +5 -2
  72. infrahub/core/migrations/graph/__init__.py +4 -0
  73. infrahub/core/migrations/graph/m001_add_version_to_graph.py +1 -1
  74. infrahub/core/migrations/graph/m002_attribute_is_default.py +2 -2
  75. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +2 -2
  76. infrahub/core/migrations/graph/m004_add_attr_documentation.py +1 -1
  77. infrahub/core/migrations/graph/m005_add_rel_read_only.py +1 -1
  78. infrahub/core/migrations/graph/m006_add_rel_on_delete.py +1 -1
  79. infrahub/core/migrations/graph/m007_add_rel_allow_override.py +1 -1
  80. infrahub/core/migrations/graph/m008_add_human_friendly_id.py +1 -1
  81. infrahub/core/migrations/graph/m009_add_generate_profile_attr.py +1 -1
  82. infrahub/core/migrations/graph/m010_add_generate_profile_attr_generic.py +1 -1
  83. infrahub/core/migrations/graph/m011_remove_profile_relationship_schema.py +2 -2
  84. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -23
  85. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -11
  86. infrahub/core/migrations/graph/m014_remove_index_attr_value.py +2 -2
  87. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
  88. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
  89. infrahub/core/migrations/graph/m017_add_core_profile.py +1 -1
  90. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -2
  91. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
  92. infrahub/core/migrations/graph/m020_add_generate_template_attr.py +48 -0
  93. infrahub/core/migrations/query/attribute_add.py +1 -1
  94. infrahub/core/migrations/query/attribute_rename.py +1 -1
  95. infrahub/core/migrations/query/delete_element_in_schema.py +1 -1
  96. infrahub/core/migrations/query/node_duplicate.py +39 -19
  97. infrahub/core/migrations/query/relationship_duplicate.py +1 -1
  98. infrahub/core/migrations/query/schema_attribute_update.py +1 -1
  99. infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
  100. infrahub/core/migrations/schema/node_remove.py +27 -13
  101. infrahub/core/migrations/schema/tasks.py +5 -5
  102. infrahub/core/migrations/shared.py +4 -4
  103. infrahub/core/models.py +7 -8
  104. infrahub/core/node/__init__.py +170 -46
  105. infrahub/core/node/base.py +1 -1
  106. infrahub/core/node/constraints/grouped_uniqueness.py +9 -2
  107. infrahub/core/node/delete_validator.py +4 -4
  108. infrahub/core/node/ipam.py +13 -8
  109. infrahub/core/node/permissions.py +4 -0
  110. infrahub/core/node/resource_manager/ip_prefix_pool.py +8 -5
  111. infrahub/core/node/standard.py +3 -5
  112. infrahub/core/property.py +1 -1
  113. infrahub/core/protocols.py +6 -0
  114. infrahub/core/protocols_base.py +4 -2
  115. infrahub/core/query/__init__.py +2 -5
  116. infrahub/core/query/attribute.py +9 -9
  117. infrahub/core/query/branch.py +5 -5
  118. infrahub/core/query/delete.py +1 -1
  119. infrahub/core/query/diff.py +45 -7
  120. infrahub/core/query/ipam.py +4 -4
  121. infrahub/core/query/node.py +19 -14
  122. infrahub/core/query/relationship.py +213 -26
  123. infrahub/core/query/resource_manager.py +13 -11
  124. infrahub/core/query/standard_node.py +6 -6
  125. infrahub/core/query/task.py +3 -3
  126. infrahub/core/query/task_log.py +1 -1
  127. infrahub/core/query/utils.py +5 -5
  128. infrahub/core/registry.py +0 -2
  129. infrahub/core/relationship/constraints/count.py +1 -1
  130. infrahub/core/relationship/constraints/peer_kind.py +1 -1
  131. infrahub/core/relationship/model.py +76 -38
  132. infrahub/core/schema/__init__.py +6 -4
  133. infrahub/core/schema/attribute_schema.py +8 -0
  134. infrahub/core/schema/basenode_schema.py +13 -3
  135. infrahub/core/schema/definitions/core/__init__.py +153 -0
  136. infrahub/core/schema/definitions/core/account.py +168 -0
  137. infrahub/core/schema/definitions/core/artifact.py +127 -0
  138. infrahub/core/schema/definitions/core/builtin.py +21 -0
  139. infrahub/core/schema/definitions/core/check.py +60 -0
  140. infrahub/core/schema/definitions/core/generator.py +96 -0
  141. infrahub/core/schema/definitions/core/graphql_query.py +77 -0
  142. infrahub/core/schema/definitions/core/group.py +105 -0
  143. infrahub/core/schema/definitions/core/ipam.py +252 -0
  144. infrahub/core/schema/definitions/core/lineage.py +17 -0
  145. infrahub/core/schema/definitions/core/menu.py +46 -0
  146. infrahub/core/schema/definitions/core/permission.py +161 -0
  147. infrahub/core/schema/definitions/core/profile.py +29 -0
  148. infrahub/core/schema/definitions/core/propose_change.py +88 -0
  149. infrahub/core/schema/definitions/core/propose_change_comment.py +188 -0
  150. infrahub/core/schema/definitions/core/propose_change_validator.py +326 -0
  151. infrahub/core/schema/definitions/core/repository.py +280 -0
  152. infrahub/core/schema/definitions/core/resource_pool.py +180 -0
  153. infrahub/core/schema/definitions/core/template.py +12 -0
  154. infrahub/core/schema/definitions/core/transform.py +87 -0
  155. infrahub/core/schema/definitions/core/webhook.py +108 -0
  156. infrahub/core/schema/definitions/internal.py +16 -0
  157. infrahub/core/schema/generated/genericnode_schema.py +5 -0
  158. infrahub/core/schema/generated/node_schema.py +5 -0
  159. infrahub/core/schema/generic_schema.py +5 -1
  160. infrahub/core/schema/manager.py +45 -42
  161. infrahub/core/schema/node_schema.py +4 -0
  162. infrahub/core/schema/profile_schema.py +4 -0
  163. infrahub/core/schema/relationship_schema.py +10 -2
  164. infrahub/core/schema/schema_branch.py +260 -16
  165. infrahub/core/schema/template_schema.py +36 -0
  166. infrahub/core/task/user_task.py +7 -5
  167. infrahub/core/timestamp.py +3 -3
  168. infrahub/core/utils.py +3 -2
  169. infrahub/core/validators/attribute/choices.py +1 -1
  170. infrahub/core/validators/attribute/enum.py +1 -1
  171. infrahub/core/validators/attribute/kind.py +1 -1
  172. infrahub/core/validators/attribute/length.py +1 -1
  173. infrahub/core/validators/attribute/optional.py +1 -1
  174. infrahub/core/validators/attribute/regex.py +1 -1
  175. infrahub/core/validators/attribute/unique.py +1 -1
  176. infrahub/core/validators/checks_runner.py +37 -0
  177. infrahub/core/validators/node/generate_profile.py +1 -1
  178. infrahub/core/validators/node/hierarchy.py +1 -1
  179. infrahub/core/validators/query.py +1 -1
  180. infrahub/core/validators/relationship/count.py +1 -1
  181. infrahub/core/validators/relationship/optional.py +1 -1
  182. infrahub/core/validators/relationship/peer.py +1 -1
  183. infrahub/core/validators/tasks.py +8 -6
  184. infrahub/core/validators/uniqueness/query.py +20 -17
  185. infrahub/database/__init__.py +16 -2
  186. infrahub/database/memgraph.py +1 -1
  187. infrahub/dependencies/builder/constraint/grouped/node_runner.py +0 -2
  188. infrahub/dependencies/builder/diff/combiner.py +1 -1
  189. infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
  190. infrahub/dependencies/builder/diff/coordinator.py +0 -2
  191. infrahub/dependencies/builder/diff/deserializer.py +4 -2
  192. infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
  193. infrahub/dependencies/builder/diff/enricher/summary_counts.py +1 -1
  194. infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
  195. infrahub/events/artifact_action.py +76 -0
  196. infrahub/events/branch_action.py +50 -21
  197. infrahub/events/group_action.py +117 -0
  198. infrahub/events/models.py +164 -51
  199. infrahub/events/node_action.py +70 -8
  200. infrahub/events/repository_action.py +8 -8
  201. infrahub/events/schema_action.py +21 -8
  202. infrahub/exceptions.py +9 -0
  203. infrahub/generators/models.py +1 -0
  204. infrahub/generators/tasks.py +34 -15
  205. infrahub/git/base.py +3 -5
  206. infrahub/git/constants.py +0 -1
  207. infrahub/git/integrator.py +60 -36
  208. infrahub/git/models.py +80 -1
  209. infrahub/git/repository.py +7 -8
  210. infrahub/git/tasks.py +432 -112
  211. infrahub/git_credential/helper.py +2 -3
  212. infrahub/graphql/analyzer.py +572 -11
  213. infrahub/graphql/app.py +34 -26
  214. infrahub/graphql/auth/query_permission_checker/anonymous_checker.py +5 -5
  215. infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +4 -4
  216. infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +4 -4
  217. infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +28 -35
  218. infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -5
  219. infrahub/graphql/context.py +33 -0
  220. infrahub/graphql/enums.py +1 -1
  221. infrahub/graphql/initialization.py +5 -1
  222. infrahub/graphql/loaders/node.py +2 -2
  223. infrahub/graphql/manager.py +63 -63
  224. infrahub/graphql/mutations/account.py +20 -13
  225. infrahub/graphql/mutations/artifact_definition.py +16 -12
  226. infrahub/graphql/mutations/branch.py +86 -40
  227. infrahub/graphql/mutations/computed_attribute.py +24 -13
  228. infrahub/graphql/mutations/diff.py +54 -14
  229. infrahub/graphql/mutations/diff_conflict.py +14 -8
  230. infrahub/graphql/mutations/generator.py +83 -0
  231. infrahub/graphql/mutations/graphql_query.py +19 -11
  232. infrahub/graphql/mutations/ipam.py +25 -23
  233. infrahub/graphql/mutations/main.py +243 -50
  234. infrahub/graphql/mutations/menu.py +10 -10
  235. infrahub/graphql/mutations/proposed_change.py +36 -28
  236. infrahub/graphql/mutations/relationship.py +343 -104
  237. infrahub/graphql/mutations/repository.py +41 -35
  238. infrahub/graphql/mutations/resource_manager.py +26 -26
  239. infrahub/graphql/mutations/schema.py +66 -33
  240. infrahub/graphql/mutations/tasks.py +16 -10
  241. infrahub/graphql/parser.py +1 -1
  242. infrahub/graphql/permissions.py +3 -10
  243. infrahub/graphql/queries/account.py +22 -18
  244. infrahub/graphql/queries/branch.py +6 -4
  245. infrahub/graphql/queries/diff/tree.py +63 -52
  246. infrahub/graphql/queries/event.py +115 -0
  247. infrahub/graphql/queries/internal.py +3 -3
  248. infrahub/graphql/queries/ipam.py +23 -18
  249. infrahub/graphql/queries/relationship.py +11 -10
  250. infrahub/graphql/queries/resource_manager.py +43 -27
  251. infrahub/graphql/queries/search.py +9 -8
  252. infrahub/graphql/queries/status.py +12 -9
  253. infrahub/graphql/queries/task.py +11 -9
  254. infrahub/graphql/resolvers/resolver.py +69 -43
  255. infrahub/graphql/resolvers/single_relationship.py +16 -10
  256. infrahub/graphql/schema.py +4 -0
  257. infrahub/graphql/subscription/__init__.py +1 -1
  258. infrahub/graphql/subscription/events.py +1 -1
  259. infrahub/graphql/subscription/graphql_query.py +8 -8
  260. infrahub/graphql/types/branch.py +2 -2
  261. infrahub/graphql/types/common.py +6 -1
  262. infrahub/graphql/types/context.py +12 -0
  263. infrahub/graphql/types/enums.py +2 -0
  264. infrahub/graphql/types/event.py +158 -0
  265. infrahub/graphql/types/interface.py +2 -2
  266. infrahub/graphql/types/node.py +3 -3
  267. infrahub/graphql/types/permission.py +2 -2
  268. infrahub/graphql/types/relationship.py +3 -3
  269. infrahub/graphql/types/standard_node.py +9 -11
  270. infrahub/graphql/utils.py +28 -182
  271. infrahub/groups/tasks.py +2 -3
  272. infrahub/lock.py +21 -21
  273. infrahub/menu/generator.py +0 -1
  274. infrahub/menu/menu.py +116 -138
  275. infrahub/menu/models.py +4 -4
  276. infrahub/message_bus/__init__.py +11 -13
  277. infrahub/message_bus/messages/__init__.py +0 -14
  278. infrahub/message_bus/messages/check_generator_run.py +1 -3
  279. infrahub/message_bus/messages/event_branch_merge.py +3 -0
  280. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +6 -0
  281. infrahub/message_bus/messages/request_proposedchange_pipeline.py +2 -0
  282. infrahub/message_bus/messages/send_echo_request.py +1 -1
  283. infrahub/message_bus/operations/__init__.py +4 -13
  284. infrahub/message_bus/operations/check/__init__.py +2 -2
  285. infrahub/message_bus/operations/check/generator.py +1 -3
  286. infrahub/message_bus/operations/event/branch.py +7 -3
  287. infrahub/message_bus/operations/event/schema.py +1 -1
  288. infrahub/message_bus/operations/event/worker.py +0 -3
  289. infrahub/message_bus/operations/finalize/validator.py +1 -1
  290. infrahub/message_bus/operations/git/file.py +2 -2
  291. infrahub/message_bus/operations/git/repository.py +1 -1
  292. infrahub/message_bus/operations/requests/__init__.py +0 -4
  293. infrahub/message_bus/operations/requests/generator_definition.py +2 -4
  294. infrahub/message_bus/operations/requests/proposed_change.py +37 -20
  295. infrahub/message_bus/operations/send/echo.py +1 -1
  296. infrahub/message_bus/types.py +1 -1
  297. infrahub/permissions/__init__.py +2 -1
  298. infrahub/permissions/globals.py +15 -0
  299. infrahub/permissions/types.py +26 -0
  300. infrahub/pools/prefix.py +29 -165
  301. infrahub/prefect_server/__init__.py +0 -0
  302. infrahub/prefect_server/app.py +18 -0
  303. infrahub/prefect_server/database.py +20 -0
  304. infrahub/prefect_server/events.py +28 -0
  305. infrahub/prefect_server/models.py +46 -0
  306. infrahub/proposed_change/models.py +18 -1
  307. infrahub/proposed_change/tasks.py +195 -53
  308. infrahub/pytest_plugin.py +4 -4
  309. infrahub/server.py +13 -12
  310. infrahub/services/__init__.py +148 -63
  311. infrahub/services/adapters/cache/__init__.py +11 -11
  312. infrahub/services/adapters/cache/nats.py +42 -25
  313. infrahub/services/adapters/cache/redis.py +3 -11
  314. infrahub/services/adapters/event/__init__.py +10 -18
  315. infrahub/services/adapters/http/__init__.py +0 -5
  316. infrahub/services/adapters/http/httpx.py +22 -15
  317. infrahub/services/adapters/message_bus/__init__.py +25 -8
  318. infrahub/services/adapters/message_bus/local.py +9 -7
  319. infrahub/services/adapters/message_bus/nats.py +14 -8
  320. infrahub/services/adapters/message_bus/rabbitmq.py +23 -10
  321. infrahub/services/adapters/workflow/__init__.py +11 -8
  322. infrahub/services/adapters/workflow/local.py +27 -6
  323. infrahub/services/adapters/workflow/worker.py +23 -7
  324. infrahub/services/component.py +43 -40
  325. infrahub/services/protocols.py +7 -7
  326. infrahub/services/scheduler.py +30 -29
  327. infrahub/storage.py +2 -4
  328. infrahub/task_manager/constants.py +1 -1
  329. infrahub/task_manager/event.py +261 -0
  330. infrahub/task_manager/models.py +147 -3
  331. infrahub/task_manager/task.py +1 -1
  332. infrahub/tasks/artifact.py +19 -18
  333. infrahub/tasks/registry.py +1 -1
  334. infrahub/tasks/telemetry.py +13 -14
  335. infrahub/transformations/tasks.py +3 -5
  336. infrahub/trigger/__init__.py +0 -0
  337. infrahub/trigger/catalogue.py +16 -0
  338. infrahub/trigger/constants.py +9 -0
  339. infrahub/trigger/models.py +105 -0
  340. infrahub/trigger/tasks.py +91 -0
  341. infrahub/types.py +1 -1
  342. infrahub/utils.py +1 -1
  343. infrahub/webhook/constants.py +0 -2
  344. infrahub/webhook/models.py +161 -40
  345. infrahub/webhook/tasks.py +123 -202
  346. infrahub/webhook/triggers.py +27 -0
  347. infrahub/workers/infrahub_async.py +36 -25
  348. infrahub/workers/utils.py +63 -0
  349. infrahub/workflows/catalogue.py +71 -52
  350. infrahub/workflows/initialization.py +14 -8
  351. infrahub/workflows/models.py +28 -4
  352. infrahub/workflows/utils.py +1 -1
  353. infrahub_sdk/client.py +8 -0
  354. infrahub_sdk/ctl/branch.py +3 -2
  355. infrahub_sdk/ctl/check.py +3 -3
  356. infrahub_sdk/ctl/cli_commands.py +16 -11
  357. infrahub_sdk/ctl/exceptions.py +0 -6
  358. infrahub_sdk/ctl/exporter.py +1 -1
  359. infrahub_sdk/ctl/generator.py +5 -5
  360. infrahub_sdk/ctl/importer.py +3 -2
  361. infrahub_sdk/ctl/menu.py +1 -1
  362. infrahub_sdk/ctl/object.py +1 -1
  363. infrahub_sdk/ctl/repository.py +23 -15
  364. infrahub_sdk/ctl/schema.py +2 -2
  365. infrahub_sdk/ctl/utils.py +4 -19
  366. infrahub_sdk/ctl/validate.py +2 -1
  367. infrahub_sdk/exceptions.py +12 -0
  368. infrahub_sdk/generator.py +3 -0
  369. infrahub_sdk/node.py +4 -4
  370. infrahub_sdk/protocols.py +21 -8
  371. infrahub_sdk/schema/__init__.py +14 -2
  372. infrahub_sdk/schema/main.py +7 -0
  373. infrahub_sdk/task/__init__.py +1 -0
  374. infrahub_sdk/task/constants.py +3 -0
  375. infrahub_sdk/task/exceptions.py +25 -0
  376. infrahub_sdk/task/manager.py +545 -0
  377. infrahub_sdk/task/models.py +74 -0
  378. infrahub_sdk/timestamp.py +134 -33
  379. infrahub_sdk/utils.py +39 -1
  380. infrahub_sdk/yaml.py +2 -3
  381. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/METADATA +47 -12
  382. infrahub_server-1.2.0b1.dist-info/RECORD +725 -0
  383. infrahub_testcontainers/container.py +14 -6
  384. infrahub_testcontainers/docker-compose.test.yml +24 -5
  385. infrahub_testcontainers/haproxy.cfg +43 -0
  386. infrahub_testcontainers/helpers.py +85 -1
  387. infrahub/core/branch/constants.py +0 -2
  388. infrahub/core/schema/definitions/core.py +0 -2274
  389. infrahub/graphql/query.py +0 -52
  390. infrahub/message_bus/messages/check_repository_checkdefinition.py +0 -20
  391. infrahub/message_bus/messages/check_repository_mergeconflicts.py +0 -16
  392. infrahub/message_bus/messages/check_repository_usercheck.py +0 -26
  393. infrahub/message_bus/messages/request_artifactdefinition_check.py +0 -17
  394. infrahub/message_bus/messages/request_repository_checks.py +0 -12
  395. infrahub/message_bus/messages/request_repository_userchecks.py +0 -18
  396. infrahub/message_bus/operations/check/repository.py +0 -293
  397. infrahub/message_bus/operations/requests/artifact_definition.py +0 -148
  398. infrahub/message_bus/operations/requests/repository.py +0 -133
  399. infrahub/schema/constants.py +0 -1
  400. infrahub/schema/tasks.py +0 -76
  401. infrahub/services/adapters/database/__init__.py +0 -9
  402. infrahub_sdk/ctl/_file.py +0 -13
  403. infrahub_server-1.1.6.dist-info/RECORD +0 -681
  404. /infrahub/{schema → artifacts}/__init__.py +0 -0
  405. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/LICENSE.txt +0 -0
  406. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/WHEEL +0 -0
  407. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/entry_points.txt +0 -0
@@ -1,9 +1,15 @@
1
1
  from collections import defaultdict
2
- from typing import AsyncGenerator, Generator
2
+ from typing import AsyncGenerator, Generator, Iterable
3
+
4
+ from neo4j.exceptions import TransientError
3
5
 
4
6
  from infrahub import config
5
7
  from infrahub.core import registry
6
8
  from infrahub.core.diff.query.field_summary import EnrichedDiffNodeFieldSummaryQuery
9
+ from infrahub.core.diff.query.summary_counts_enricher import (
10
+ DiffFieldsSummaryCountsEnricherQuery,
11
+ DiffNodesSummaryCountsEnricherQuery,
12
+ )
7
13
  from infrahub.core.query.diff import DiffCountChanges
8
14
  from infrahub.core.timestamp import Timestamp
9
15
  from infrahub.database import InfrahubDatabase, retry_db_transaction
@@ -13,6 +19,7 @@ from infrahub.log import get_logger
13
19
  from ..model.path import (
14
20
  ConflictSelection,
15
21
  EnrichedDiffConflict,
22
+ EnrichedDiffNode,
16
23
  EnrichedDiffRoot,
17
24
  EnrichedDiffRootMetadata,
18
25
  EnrichedDiffs,
@@ -26,13 +33,13 @@ from ..query.all_conflicts import EnrichedDiffAllConflictsQuery
26
33
  from ..query.delete_query import EnrichedDiffDeleteQuery
27
34
  from ..query.diff_get import EnrichedDiffGetQuery
28
35
  from ..query.diff_summary import DiffSummaryCounters, DiffSummaryQuery
29
- from ..query.drop_tracking_id import EnrichedDiffDropTrackingIdQuery
30
36
  from ..query.field_specifiers import EnrichedDiffFieldSpecifiersQuery
31
37
  from ..query.filters import EnrichedDiffQueryFilters
32
38
  from ..query.get_conflict_query import EnrichedDiffConflictQuery
33
39
  from ..query.has_conflicts_query import EnrichedDiffHasConflictQuery
40
+ from ..query.merge_tracking_id import EnrichedDiffMergedTrackingIdQuery
34
41
  from ..query.roots_metadata import EnrichedDiffRootsMetadataQuery
35
- from ..query.save import EnrichedDiffRootsCreateQuery, EnrichedNodeBatchCreateQuery, EnrichedNodesLinkQuery
42
+ from ..query.save import EnrichedDiffRootsUpsertQuery, EnrichedNodeBatchCreateQuery, EnrichedNodesLinkQuery
36
43
  from ..query.time_range_query import EnrichedDiffTimeRangeQuery
37
44
  from ..query.update_conflict_query import EnrichedDiffConflictUpdateQuery
38
45
  from .deserializer import EnrichedDiffDeserializer
@@ -41,17 +48,17 @@ log = get_logger()
41
48
 
42
49
 
43
50
  class DiffRepository:
44
- MAX_SAVE_BATCH_SIZE: int = 100
45
-
46
- def __init__(self, db: InfrahubDatabase, deserializer: EnrichedDiffDeserializer):
51
+ def __init__(self, db: InfrahubDatabase, deserializer: EnrichedDiffDeserializer, max_save_batch_size: int = 1000):
47
52
  self.db = db
48
53
  self.deserializer = deserializer
54
+ self.max_save_batch_size = max_save_batch_size
49
55
 
50
56
  async def _run_get_diff_query(
51
57
  self,
52
58
  base_branch_name: str,
53
59
  diff_branch_names: list[str],
54
- limit: int,
60
+ batch_size_limit: int,
61
+ limit: int | None = None,
55
62
  from_time: Timestamp | None = None,
56
63
  to_time: Timestamp | None = None,
57
64
  filters: EnrichedDiffQueryFilters | None = None,
@@ -62,8 +69,13 @@ class DiffRepository:
62
69
  diff_ids: list[str] | None = None,
63
70
  ) -> list[EnrichedDiffRoot]:
64
71
  self.deserializer.initialize()
72
+ final_row_number = None
73
+ if limit:
74
+ final_row_number = offset + limit
65
75
  has_more_data = True
66
- while has_more_data:
76
+ while has_more_data and (final_row_number is None or offset < final_row_number):
77
+ if final_row_number is not None and offset + batch_size_limit > final_row_number:
78
+ batch_size_limit = final_row_number - offset
67
79
  get_query = await EnrichedDiffGetQuery.init(
68
80
  db=self.db,
69
81
  base_branch_name=base_branch_name,
@@ -72,12 +84,12 @@ class DiffRepository:
72
84
  to_time=to_time,
73
85
  filters=filters,
74
86
  max_depth=max_depth,
75
- limit=limit,
87
+ limit=batch_size_limit,
76
88
  offset=offset,
77
89
  tracking_id=tracking_id,
78
90
  diff_ids=diff_ids,
79
91
  )
80
- log.info(f"Beginning enriched diff get query {limit=}, {offset=}")
92
+ log.info(f"Beginning enriched diff get query {batch_size_limit=}, {offset=}")
81
93
  await get_query.execute(db=self.db)
82
94
  log.info("Enriched diff get query complete")
83
95
  last_result = None
@@ -87,7 +99,7 @@ class DiffRepository:
87
99
  has_more_data = False
88
100
  if last_result:
89
101
  has_more_data = last_result.get_as_type("has_more_data", bool)
90
- offset += limit
102
+ offset += batch_size_limit
91
103
  return await self.deserializer.deserialize()
92
104
 
93
105
  async def get(
@@ -105,16 +117,17 @@ class DiffRepository:
105
117
  include_empty: bool = False,
106
118
  ) -> list[EnrichedDiffRoot]:
107
119
  final_max_depth = config.SETTINGS.database.max_depth_search_hierarchy
108
- limit = limit or int(config.SETTINGS.database.query_size_limit / 10)
120
+ batch_size_limit = int(config.SETTINGS.database.query_size_limit / 10)
109
121
  diff_roots = await self._run_get_diff_query(
110
122
  base_branch_name=base_branch_name,
111
123
  diff_branch_names=diff_branch_names,
124
+ batch_size_limit=batch_size_limit,
125
+ limit=limit,
112
126
  from_time=from_time,
113
127
  to_time=to_time,
114
128
  filters=EnrichedDiffQueryFilters(**dict(filters or {})),
115
129
  include_parents=include_parents,
116
130
  max_depth=final_max_depth,
117
- limit=limit,
118
131
  offset=offset or 0,
119
132
  tracking_id=tracking_id,
120
133
  diff_ids=diff_ids,
@@ -131,42 +144,56 @@ class DiffRepository:
131
144
  to_time: Timestamp,
132
145
  ) -> list[EnrichedDiffs]:
133
146
  max_depth = config.SETTINGS.database.max_depth_search_hierarchy
134
- limit = int(config.SETTINGS.database.query_size_limit / 10)
147
+ batch_size_limit = int(config.SETTINGS.database.query_size_limit / 10)
135
148
  diff_branch_roots = await self._run_get_diff_query(
136
149
  base_branch_name=base_branch_name,
137
150
  diff_branch_names=[diff_branch_name],
138
151
  from_time=from_time,
139
152
  to_time=to_time,
140
153
  max_depth=max_depth,
141
- limit=limit,
154
+ batch_size_limit=batch_size_limit,
142
155
  )
143
156
  diffs_by_uuid = {dbr.uuid: dbr for dbr in diff_branch_roots}
144
157
  base_branch_roots = await self._run_get_diff_query(
145
158
  base_branch_name=base_branch_name,
146
159
  diff_branch_names=[base_branch_name],
147
160
  max_depth=max_depth,
148
- limit=limit,
149
- diff_ids=[d.partner_uuid for d in diffs_by_uuid.values()],
161
+ batch_size_limit=batch_size_limit,
162
+ diff_ids=[d.partner_uuid for d in diffs_by_uuid.values() if d.partner_uuid],
150
163
  )
151
164
  diffs_by_uuid.update({bbr.uuid: bbr for bbr in base_branch_roots})
152
- return [
153
- EnrichedDiffs(
154
- base_branch_name=base_branch_name,
155
- diff_branch_name=diff_branch_name,
156
- base_branch_diff=diffs_by_uuid[dbr.partner_uuid],
157
- diff_branch_diff=dbr,
165
+ diff_pairs = []
166
+ for dbr in diff_branch_roots:
167
+ if dbr.partner_uuid is None:
168
+ continue
169
+ base_branch_diff = diffs_by_uuid[dbr.partner_uuid]
170
+ diff_pairs.append(
171
+ EnrichedDiffs(
172
+ base_branch_name=base_branch_name,
173
+ diff_branch_name=diff_branch_name,
174
+ base_branch_diff=base_branch_diff,
175
+ diff_branch_diff=dbr,
176
+ )
158
177
  )
159
- for dbr in diff_branch_roots
160
- ]
178
+ return diff_pairs
161
179
 
162
- async def hydrate_diff_pair(self, enriched_diffs_metadata: EnrichedDiffsMetadata) -> EnrichedDiffs:
180
+ async def hydrate_diff_pair(
181
+ self,
182
+ enriched_diffs_metadata: EnrichedDiffsMetadata,
183
+ node_uuids: Iterable[str] | None = None,
184
+ ) -> EnrichedDiffs:
185
+ filters = None
186
+ if node_uuids:
187
+ filters = {"ids": list(node_uuids) if node_uuids is not None else None}
163
188
  hydrated_base_diff = await self.get_one(
164
189
  diff_branch_name=enriched_diffs_metadata.base_branch_name,
165
190
  diff_id=enriched_diffs_metadata.base_branch_diff.uuid,
191
+ filters=filters,
166
192
  )
167
193
  hydrated_branch_diff = await self.get_one(
168
194
  diff_branch_name=enriched_diffs_metadata.diff_branch_name,
169
195
  diff_id=enriched_diffs_metadata.diff_branch_diff.uuid,
196
+ filters=filters,
170
197
  )
171
198
  return EnrichedDiffs(
172
199
  base_branch_name=enriched_diffs_metadata.base_branch_name,
@@ -208,26 +235,111 @@ class DiffRepository:
208
235
  ) -> Generator[list[EnrichedNodeCreateRequest], None, None]:
209
236
  node_requests = []
210
237
  for diff_root in (enriched_diffs.base_branch_diff, enriched_diffs.diff_branch_diff):
238
+ size_count = 0
211
239
  for node in diff_root.nodes:
212
- node_requests.append(EnrichedNodeCreateRequest(node=node, root_uuid=diff_root.uuid))
213
- if len(node_requests) == self.MAX_SAVE_BATCH_SIZE:
240
+ node_size_count = node.num_properties
241
+ if size_count + node_size_count < self.max_save_batch_size:
242
+ node_requests.append(EnrichedNodeCreateRequest(node=node, root_uuid=diff_root.uuid))
243
+ size_count += node_size_count
244
+ else:
245
+ log.info(f"Num nodes in batch: {len(node_requests)}, num properties in batch: {size_count}")
214
246
  yield node_requests
215
- node_requests = []
247
+ size_count = node_size_count
248
+ node_requests = [EnrichedNodeCreateRequest(node=node, root_uuid=diff_root.uuid)]
216
249
  if node_requests:
250
+ log.info(f"Num nodes in batch: {len(node_requests)}, num properties in batch: {size_count}")
217
251
  yield node_requests
218
252
 
219
- @retry_db_transaction(name="enriched_diff_save")
220
- async def save(self, enriched_diffs: EnrichedDiffs) -> None:
221
- num_nodes = len(enriched_diffs.base_branch_diff.nodes) + len(enriched_diffs.diff_branch_diff.nodes)
222
- log.info(f"Saving diff (num_nodes={num_nodes})...")
223
- root_query = await EnrichedDiffRootsCreateQuery.init(db=self.db, enriched_diffs=enriched_diffs)
253
+ @retry_db_transaction(name="enriched_diff_metadata_save")
254
+ async def _save_root_metadata(self, enriched_diffs: EnrichedDiffsMetadata) -> None:
255
+ log.info("Updating diff metadata...")
256
+ root_query = await EnrichedDiffRootsUpsertQuery.init(db=self.db, enriched_diffs=enriched_diffs)
224
257
  await root_query.execute(db=self.db)
225
- for node_create_batch in self._get_node_create_request_batch(enriched_diffs=enriched_diffs):
226
- node_query = await EnrichedNodeBatchCreateQuery.init(db=self.db, node_create_batch=node_create_batch)
258
+ log.info("Diff metadata updated.")
259
+
260
+ async def _save_node_batch(self, node_create_batch: list[EnrichedNodeCreateRequest]) -> None:
261
+ node_query = await EnrichedNodeBatchCreateQuery.init(db=self.db, node_create_batch=node_create_batch)
262
+ try:
227
263
  await node_query.execute(db=self.db)
228
- link_query = await EnrichedNodesLinkQuery.init(db=self.db, enriched_diffs=enriched_diffs)
264
+ except TransientError as exc:
265
+ if not exc.code or "OutOfMemoryError".lower() not in str(exc.code).lower():
266
+ raise
267
+ log.exception("Database memory error during save. Trying smaller transactions")
268
+ for node_request in node_create_batch:
269
+ log.info(
270
+ f"Updating node {node_request.node.uuid}, num_properties={node_request.node.num_properties}..."
271
+ )
272
+ single_node_query = await EnrichedNodeBatchCreateQuery.init(
273
+ db=self.db, node_create_batch=[node_request]
274
+ )
275
+ await single_node_query.execute(db=self.db)
276
+
277
+ @retry_db_transaction(name="enriched_diff_hierarchy_update")
278
+ async def _run_hierarchy_links_update_query(self, diff_root_uuid: str, diff_nodes: list[EnrichedDiffNode]) -> None:
279
+ log.info(f"Updating diff hierarchy links, num_nodes={len(diff_nodes)}")
280
+ link_query = await EnrichedNodesLinkQuery.init(db=self.db, diff_root_uuid=diff_root_uuid, diff_nodes=diff_nodes)
229
281
  await link_query.execute(db=self.db)
230
- log.info("Diff saved.")
282
+
283
+ async def _update_hierarchy_links(self, enriched_diffs: EnrichedDiffs) -> None:
284
+ for diff_root in (enriched_diffs.base_branch_diff, enriched_diffs.diff_branch_diff):
285
+ nodes_to_update = []
286
+ for node in diff_root.nodes:
287
+ if any(r.nodes for r in node.relationships):
288
+ nodes_to_update.append(node)
289
+ if len(nodes_to_update) >= config.SETTINGS.database.query_size_limit:
290
+ await self._run_hierarchy_links_update_query(
291
+ diff_root_uuid=diff_root.uuid, diff_nodes=nodes_to_update
292
+ )
293
+ nodes_to_update = []
294
+ if nodes_to_update:
295
+ await self._run_hierarchy_links_update_query(diff_root_uuid=diff_root.uuid, diff_nodes=nodes_to_update)
296
+
297
+ async def _update_summary_counts(self, diff_root: EnrichedDiffRoot) -> None:
298
+ max_nodes_limit = config.SETTINGS.database.query_size_limit
299
+ num_nodes = len(diff_root.nodes)
300
+ if diff_root.exists_on_database and num_nodes < max_nodes_limit:
301
+ await self.add_summary_counts(
302
+ diff_branch_name=diff_root.diff_branch_name,
303
+ diff_id=diff_root.uuid,
304
+ node_uuids=None,
305
+ )
306
+ return
307
+ node_uuids: list[str] = []
308
+ for diff_node in diff_root.nodes:
309
+ node_uuids.append(diff_node.uuid)
310
+ if len(node_uuids) >= max_nodes_limit:
311
+ await self.add_summary_counts(
312
+ diff_branch_name=diff_root.diff_branch_name,
313
+ diff_id=diff_root.uuid,
314
+ node_uuids=node_uuids,
315
+ )
316
+ node_uuids = []
317
+ if node_uuids:
318
+ await self.add_summary_counts(
319
+ diff_branch_name=diff_root.diff_branch_name,
320
+ diff_id=diff_root.uuid,
321
+ node_uuids=node_uuids,
322
+ )
323
+
324
+ async def save(self, enriched_diffs: EnrichedDiffs | EnrichedDiffsMetadata, do_summary_counts: bool = True) -> None:
325
+ # metadata-only update
326
+ if not isinstance(enriched_diffs, EnrichedDiffs):
327
+ await self._save_root_metadata(enriched_diffs=enriched_diffs)
328
+ return
329
+
330
+ count_nodes_remaining = len(enriched_diffs.base_branch_diff.nodes) + len(enriched_diffs.diff_branch_diff.nodes)
331
+ log.info(f"Saving diff (num_nodes={count_nodes_remaining})...")
332
+ for batch_num, node_create_batch in enumerate(
333
+ self._get_node_create_request_batch(enriched_diffs=enriched_diffs)
334
+ ):
335
+ log.info(f"Saving node batch #{batch_num}...")
336
+ await self._save_node_batch(node_create_batch=node_create_batch)
337
+ count_nodes_remaining -= len(node_create_batch)
338
+ log.info(f"Batch saved. {count_nodes_remaining=}")
339
+ await self._update_hierarchy_links(enriched_diffs=enriched_diffs)
340
+ if do_summary_counts:
341
+ await self._update_summary_counts(diff_root=enriched_diffs.diff_branch_diff)
342
+ await self._save_root_metadata(enriched_diffs=enriched_diffs)
231
343
 
232
344
  async def summary(
233
345
  self,
@@ -277,6 +389,7 @@ class DiffRepository:
277
389
  base_branch_names: list[str] | None = None,
278
390
  from_time: Timestamp | None = None,
279
391
  to_time: Timestamp | None = None,
392
+ tracking_id: TrackingId | None = None,
280
393
  ) -> list[EnrichedDiffsMetadata]:
281
394
  if diff_branch_names and base_branch_names:
282
395
  diff_branch_names += base_branch_names
@@ -285,11 +398,12 @@ class DiffRepository:
285
398
  base_branch_names=base_branch_names,
286
399
  from_time=from_time,
287
400
  to_time=to_time,
401
+ tracking_id=tracking_id,
288
402
  )
289
403
  roots_by_id = {root.uuid: root for root in empty_roots}
290
404
  pairs: list[EnrichedDiffsMetadata] = []
291
405
  for branch_root in empty_roots:
292
- if branch_root.base_branch_name == branch_root.diff_branch_name:
406
+ if branch_root.base_branch_name == branch_root.diff_branch_name or branch_root.partner_uuid is None:
293
407
  continue
294
408
  base_root = roots_by_id[branch_root.partner_uuid]
295
409
  pairs.append(
@@ -308,6 +422,7 @@ class DiffRepository:
308
422
  base_branch_names: list[str] | None = None,
309
423
  from_time: Timestamp | None = None,
310
424
  to_time: Timestamp | None = None,
425
+ tracking_id: TrackingId | None = None,
311
426
  ) -> list[EnrichedDiffRootMetadata]:
312
427
  query = await EnrichedDiffRootsMetadataQuery.init(
313
428
  db=self.db,
@@ -315,6 +430,7 @@ class DiffRepository:
315
430
  base_branch_names=base_branch_names,
316
431
  from_time=from_time,
317
432
  to_time=to_time,
433
+ tracking_id=tracking_id,
318
434
  )
319
435
  await query.execute(db=self.db)
320
436
  diff_roots = []
@@ -374,8 +490,8 @@ class DiffRepository:
374
490
  await query.execute(db=self.db)
375
491
  return await query.get_field_summaries()
376
492
 
377
- async def drop_tracking_ids(self, tracking_ids: list[TrackingId]) -> None:
378
- query = await EnrichedDiffDropTrackingIdQuery.init(db=self.db, tracking_ids=tracking_ids)
493
+ async def mark_tracking_ids_merged(self, tracking_ids: list[TrackingId]) -> None:
494
+ query = await EnrichedDiffMergedTrackingIdQuery.init(db=self.db, tracking_ids=tracking_ids)
379
495
  await query.execute(db=self.db)
380
496
 
381
497
  async def get_num_changes_in_time_range_by_branch(
@@ -400,3 +516,61 @@ class DiffRepository:
400
516
  break
401
517
  offset += limit
402
518
  return specifiers
519
+
520
+ async def add_summary_counts(
521
+ self,
522
+ diff_branch_name: str,
523
+ tracking_id: TrackingId | None = None,
524
+ diff_id: str | None = None,
525
+ node_uuids: list[str] | None = None,
526
+ ) -> None:
527
+ await self._add_field_summary_counts(
528
+ diff_branch_name=diff_branch_name,
529
+ tracking_id=tracking_id,
530
+ diff_id=diff_id,
531
+ node_uuids=node_uuids,
532
+ )
533
+ await self._add_node_summary_counts(
534
+ diff_branch_name=diff_branch_name,
535
+ tracking_id=tracking_id,
536
+ diff_id=diff_id,
537
+ node_uuids=node_uuids,
538
+ )
539
+
540
+ @retry_db_transaction(name="enriched_diff_field_summary_counts")
541
+ async def _add_field_summary_counts(
542
+ self,
543
+ diff_branch_name: str,
544
+ tracking_id: TrackingId | None = None,
545
+ diff_id: str | None = None,
546
+ node_uuids: list[str] | None = None,
547
+ ) -> None:
548
+ log.info("Updating field summary counts...")
549
+ query = await DiffFieldsSummaryCountsEnricherQuery.init(
550
+ db=self.db,
551
+ diff_branch_name=diff_branch_name,
552
+ tracking_id=tracking_id,
553
+ diff_id=diff_id,
554
+ node_uuids=node_uuids,
555
+ )
556
+ await query.execute(db=self.db)
557
+ log.info("Field summary counts updated.")
558
+
559
+ @retry_db_transaction(name="enriched_diff_node_summary_counts")
560
+ async def _add_node_summary_counts(
561
+ self,
562
+ diff_branch_name: str,
563
+ tracking_id: TrackingId | None = None,
564
+ diff_id: str | None = None,
565
+ node_uuids: list[str] | None = None,
566
+ ) -> None:
567
+ log.info("Updating node summary counts...")
568
+ query = await DiffNodesSummaryCountsEnricherQuery.init(
569
+ db=self.db,
570
+ diff_branch_name=diff_branch_name,
571
+ tracking_id=tracking_id,
572
+ diff_id=diff_id,
573
+ node_uuids=node_uuids,
574
+ )
575
+ await query.execute(db=self.db)
576
+ log.info("node summary counts updated.")
@@ -1,22 +1,24 @@
1
+ from __future__ import annotations
2
+
1
3
  from prefect import flow
2
4
 
5
+ from infrahub.context import InfrahubContext # noqa: TC001 needed for prefect flow
3
6
  from infrahub.core import registry
4
7
  from infrahub.core.diff.coordinator import DiffCoordinator
5
- from infrahub.core.diff.models import RequestDiffUpdate
8
+ from infrahub.core.diff.models import RequestDiffUpdate # noqa: TC001 needed for prefect flow
6
9
  from infrahub.core.diff.repository.repository import DiffRepository
7
10
  from infrahub.dependencies.registry import get_component_registry
8
11
  from infrahub.log import get_logger
9
- from infrahub.services import services
12
+ from infrahub.services import InfrahubServices # noqa: TC001 needed for prefect flow
10
13
  from infrahub.workflows.catalogue import DIFF_REFRESH
11
- from infrahub.workflows.utils import add_branch_tag
14
+ from infrahub.workflows.utils import add_tags
12
15
 
13
16
  log = get_logger()
14
17
 
15
18
 
16
19
  @flow(name="diff-update", flow_run_name="Update diff for branch {model.branch_name}")
17
- async def update_diff(model: RequestDiffUpdate) -> None:
18
- service = services.service
19
- await add_branch_tag(branch_name=model.branch_name)
20
+ async def update_diff(model: RequestDiffUpdate, service: InfrahubServices) -> None:
21
+ await add_tags(branches=[model.branch_name])
20
22
 
21
23
  async with service.database.start_session() as db:
22
24
  component_registry = get_component_registry()
@@ -35,9 +37,8 @@ async def update_diff(model: RequestDiffUpdate) -> None:
35
37
 
36
38
 
37
39
  @flow(name="diff-refresh", flow_run_name="Recreate diff for branch {branch_name}")
38
- async def refresh_diff(branch_name: str, diff_id: str) -> None:
39
- service = services.service
40
- await add_branch_tag(branch_name=branch_name)
40
+ async def refresh_diff(branch_name: str, diff_id: str, service: InfrahubServices) -> None:
41
+ await add_tags(branches=[branch_name])
41
42
 
42
43
  async with service.database.start_session() as db:
43
44
  component_registry = get_component_registry()
@@ -49,9 +50,8 @@ async def refresh_diff(branch_name: str, diff_id: str) -> None:
49
50
 
50
51
 
51
52
  @flow(name="diff-refresh-all", flow_run_name="Recreate all diffs for branch {branch_name}")
52
- async def refresh_diff_all(branch_name: str) -> None:
53
- service = services.service
54
- await add_branch_tag(branch_name=branch_name)
53
+ async def refresh_diff_all(branch_name: str, context: InfrahubContext, service: InfrahubServices) -> None:
54
+ await add_tags(branches=[branch_name])
55
55
 
56
56
  async with service.database.start_session() as db:
57
57
  component_registry = get_component_registry()
@@ -63,5 +63,6 @@ async def refresh_diff_all(branch_name: str) -> None:
63
63
  if diff_root.base_branch_name != diff_root.diff_branch_name:
64
64
  await service.workflow.submit_workflow(
65
65
  workflow=DIFF_REFRESH,
66
+ context=context,
66
67
  parameters={"branch_name": diff_root.diff_branch_name, "diff_id": diff_root.uuid},
67
68
  )
infrahub/core/enums.py CHANGED
@@ -2,7 +2,7 @@ import enum
2
2
  import re
3
3
  from typing import Any
4
4
 
5
- ENUM_NAME_REGEX = re.compile("[_a-zA-Z0-9]+")
5
+ ENUM_NAME_REGEX = re.compile(r"[_a-zA-Z0-9]+")
6
6
 
7
7
 
8
8
  def generate_python_enum(name: str, options: list[Any]) -> type[enum.Enum]:
@@ -1 +1 @@
1
- GRAPH_VERSION = 18
1
+ GRAPH_VERSION = 20
@@ -12,6 +12,9 @@ node_indexes: list[IndexItem] = [
12
12
  IndexItem(name="attr_iphost_bin", label="AttributeIPHost", properties=["binary_address"], type=IndexType.RANGE),
13
13
  IndexItem(name="rel_uuid", label="Relationship", properties=["uuid"], type=IndexType.RANGE),
14
14
  IndexItem(name="rel_identifier", label="Relationship", properties=["name"], type=IndexType.RANGE),
15
+ # diff indices
16
+ IndexItem(name="diff_uuid", label="DiffRoot", properties=["uuid"], type=IndexType.TEXT),
17
+ IndexItem(name="diff_node_uuid", label="DiffNode", properties=["uuid"], type=IndexType.TEXT),
15
18
  ]
16
19
 
17
20
  rel_indexes: list[IndexItem] = [
@@ -17,7 +17,7 @@ class ObjectConflictValidatorRecorder:
17
17
  self.validator_label = validator_label
18
18
  self.check_schema_kind = check_schema_kind
19
19
 
20
- async def record_conflicts(self, proposed_change_id: str, conflicts: Sequence[ObjectConflict]) -> list[Node]: # pylint: disable=too-many-branches
20
+ async def record_conflicts(self, proposed_change_id: str, conflicts: Sequence[ObjectConflict]) -> list[Node]:
21
21
  try:
22
22
  proposed_change = await NodeManager.get_one_by_id_or_default_filter(
23
23
  id=proposed_change_id, kind=InfrahubKind.PROPOSEDCHANGE, db=self.db
@@ -104,7 +104,7 @@ class IpamReconciler:
104
104
  ip_node_uuid = query.get_ip_node_uuid()
105
105
  if not ip_node_uuid:
106
106
  node_type = InfrahubKind.IPPREFIX
107
- if isinstance(ip_value, (ipaddress.IPv6Interface, ipaddress.IPv4Interface)):
107
+ if isinstance(ip_value, ipaddress.IPv6Interface | ipaddress.IPv4Interface):
108
108
  node_type = InfrahubKind.IPADDRESS
109
109
  raise NodeNotFoundError(node_type=node_type, identifier=str(ip_value))
110
110
  current_parent_uuid = query.get_current_parent_uuid()
@@ -5,7 +5,7 @@ from prefect import flow
5
5
 
6
6
  from infrahub.core import registry
7
7
  from infrahub.core.ipam.reconciler import IpamReconciler
8
- from infrahub.services import services
8
+ from infrahub.services import InfrahubServices
9
9
  from infrahub.workflows.utils import add_branch_tag
10
10
 
11
11
  from .model import IpamNodeDetails
@@ -20,8 +20,7 @@ if TYPE_CHECKING:
20
20
  description="Ensure the IPAM Tree is up to date",
21
21
  persist_result=False,
22
22
  )
23
- async def ipam_reconciliation(branch: str, ipam_node_details: list[IpamNodeDetails]) -> None:
24
- service = services.service
23
+ async def ipam_reconciliation(branch: str, ipam_node_details: list[IpamNodeDetails], service: InfrahubServices) -> None:
25
24
  async with service.database.start_session() as db:
26
25
  branch_obj = await registry.get_branch(db=db, branch=branch)
27
26
 
infrahub/core/manager.py CHANGED
@@ -23,7 +23,14 @@ from infrahub.core.query.node import (
23
23
  from infrahub.core.query.relationship import RelationshipGetPeerQuery
24
24
  from infrahub.core.registry import registry
25
25
  from infrahub.core.relationship import Relationship, RelationshipManager
26
- from infrahub.core.schema import GenericSchema, MainSchemaTypes, NodeSchema, ProfileSchema, RelationshipSchema
26
+ from infrahub.core.schema import (
27
+ GenericSchema,
28
+ MainSchemaTypes,
29
+ NodeSchema,
30
+ ProfileSchema,
31
+ RelationshipSchema,
32
+ TemplateSchema,
33
+ )
27
34
  from infrahub.core.timestamp import Timestamp
28
35
  from infrahub.exceptions import NodeNotFoundError, ProcessingError, SchemaNotFoundError
29
36
  from infrahub.graphql.models import OrderModel
@@ -35,8 +42,6 @@ if TYPE_CHECKING:
35
42
 
36
43
  SchemaProtocol = TypeVar("SchemaProtocol")
37
44
 
38
- # pylint: disable=redefined-builtin,too-many-lines
39
-
40
45
 
41
46
  def identify_node_class(node: NodeToProcess) -> type[Node]:
42
47
  """Identify the proper class to use to create the NodeObject.
@@ -61,7 +66,7 @@ def get_schema(
61
66
  ) -> MainSchemaTypes:
62
67
  if isinstance(node_schema, str):
63
68
  return db.schema.get(name=node_schema, branch=branch.name)
64
- if hasattr(node_schema, "_is_runtime_protocol") and getattr(node_schema, "_is_runtime_protocol"):
69
+ if hasattr(node_schema, "_is_runtime_protocol") and node_schema._is_runtime_protocol:
65
70
  return db.schema.get(name=node_schema.__name__, branch=branch.name)
66
71
  if not isinstance(node_schema, (MainSchemaTypes)):
67
72
  raise ValueError(f"Invalid schema provided {node_schema}")
@@ -129,7 +134,7 @@ class NodeManager:
129
134
  async def query(
130
135
  cls,
131
136
  db: InfrahubDatabase,
132
- schema: Union[NodeSchema, GenericSchema, ProfileSchema, str],
137
+ schema: Union[NodeSchema, GenericSchema, ProfileSchema, TemplateSchema, str],
133
138
  filters: dict | None = ...,
134
139
  fields: dict | None = ...,
135
140
  offset: int | None = ...,
@@ -267,11 +272,11 @@ class NodeManager:
267
272
  async def count(
268
273
  cls,
269
274
  db: InfrahubDatabase,
270
- schema: Union[type[SchemaProtocol], NodeSchema, GenericSchema, ProfileSchema, str],
275
+ schema: Union[type[SchemaProtocol], NodeSchema, GenericSchema, ProfileSchema, TemplateSchema, str],
271
276
  filters: Optional[dict] = None,
272
277
  at: Optional[Union[Timestamp, str]] = None,
273
278
  branch: Optional[Union[Branch, str]] = None,
274
- account=None, # pylint: disable=unused-argument
279
+ account=None, # noqa: ARG003
275
280
  partial_match: bool = False,
276
281
  branch_agnostic: bool = False,
277
282
  ) -> int:
@@ -446,7 +451,7 @@ class NodeManager:
446
451
  limit: Optional[int] = None,
447
452
  at: Optional[Union[Timestamp, str]] = None,
448
453
  branch: Optional[Union[Branch, str]] = None,
449
- ) -> dict[str, Any]:
454
+ ) -> dict[str, Node]:
450
455
  branch = await registry.get_branch(branch=branch, db=db)
451
456
  at = Timestamp(at)
452
457
 
@@ -489,7 +494,7 @@ class NodeManager:
489
494
  kind: type[SchemaProtocol],
490
495
  at: Timestamp | str | None = ...,
491
496
  branch: Branch | str | None = ...,
492
- id: str | None = ..., # pylint: disable=redefined-builtin
497
+ id: str | None = ...,
493
498
  hfid: list[str] | None = ...,
494
499
  ) -> SchemaProtocol: ...
495
500
 
@@ -501,7 +506,7 @@ class NodeManager:
501
506
  kind: str,
502
507
  at: Timestamp | str | None = ...,
503
508
  branch: Branch | str | None = ...,
504
- id: str | None = ..., # pylint: disable=redefined-builtin
509
+ id: str | None = ...,
505
510
  hfid: list[str] | None = ...,
506
511
  ) -> Any: ...
507
512
 
@@ -512,7 +517,7 @@ class NodeManager:
512
517
  kind: type[SchemaProtocol] | str,
513
518
  at: Timestamp | str | None = None,
514
519
  branch: Branch | str | None = None,
515
- id: str | None = None, # pylint: disable=redefined-builtin
520
+ id: str | None = None,
516
521
  hfid: list[str] | None = None,
517
522
  ) -> Any:
518
523
  if not id and not hfid:
@@ -802,7 +807,7 @@ class NodeManager:
802
807
  raise NodeNotFoundError(branch_name=branch.name, node_type=kind_str, identifier=hfid_str)
803
808
 
804
809
  filters = {}
805
- for key, item in zip(node_schema.human_friendly_id, hfid):
810
+ for key, item in zip(node_schema.human_friendly_id, hfid, strict=False):
806
811
  path = node_schema.parse_schema_path(path=key, schema=registry.schema.get_schema_branch(name=branch.name))
807
812
 
808
813
  if path.is_type_relationship:
@@ -1007,7 +1012,7 @@ class NodeManager:
1007
1012
  cls,
1008
1013
  id: str,
1009
1014
  db: InfrahubDatabase,
1010
- kind: Literal[None] = ...,
1015
+ kind: None = ...,
1011
1016
  raise_on_error: bool = ...,
1012
1017
  fields: dict | None = ...,
1013
1018
  at: Timestamp | str | None = ...,
@@ -1148,7 +1153,7 @@ class NodeManager:
1148
1153
 
1149
1154
  nodes: dict[str, Node] = {}
1150
1155
 
1151
- for node_id in ids: # pylint: disable=too-many-nested-blocks
1156
+ for node_id in ids:
1152
1157
  if node_id not in nodes_info_by_id:
1153
1158
  continue
1154
1159
 
@@ -1310,7 +1315,7 @@ class NodeManager:
1310
1315
  nodes: list[Node],
1311
1316
  branch: Optional[Union[Branch, str]] = None,
1312
1317
  at: Optional[Union[Timestamp, str]] = None,
1313
- ) -> list[Any]:
1318
+ ) -> list[Node]:
1314
1319
  """Returns list of deleted nodes because of cascading deletes"""
1315
1320
  branch = await registry.get_branch(branch=branch, db=db)
1316
1321
  node_delete_validator = NodeDeleteValidator(db=db, branch=branch)