infrahub-server 1.1.9__py3-none-any.whl → 1.2.0__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 (467) hide show
  1. infrahub/api/artifact.py +16 -4
  2. infrahub/api/dependencies.py +14 -6
  3. infrahub/api/diff/validation_models.py +7 -7
  4. infrahub/api/oauth2.py +0 -1
  5. infrahub/api/oidc.py +0 -1
  6. infrahub/api/query.py +18 -7
  7. infrahub/api/schema.py +33 -7
  8. infrahub/api/transformation.py +12 -5
  9. infrahub/{message_bus/messages/check_artifact_create.py → artifacts/models.py} +6 -6
  10. infrahub/{message_bus/operations/check/artifact.py → artifacts/tasks.py} +27 -28
  11. infrahub/cli/__init__.py +12 -10
  12. infrahub/cli/constants.py +3 -0
  13. infrahub/cli/db.py +166 -185
  14. infrahub/cli/events.py +8 -3
  15. infrahub/cli/git_agent.py +9 -7
  16. infrahub/cli/tasks.py +4 -6
  17. infrahub/cli/upgrade.py +146 -0
  18. infrahub/computed_attribute/gather.py +174 -0
  19. infrahub/computed_attribute/models.py +202 -11
  20. infrahub/computed_attribute/tasks.py +103 -421
  21. infrahub/computed_attribute/triggers.py +56 -0
  22. infrahub/config.py +33 -33
  23. infrahub/context.py +53 -0
  24. infrahub/core/account.py +9 -12
  25. infrahub/core/attribute.py +104 -75
  26. infrahub/core/branch/models.py +4 -4
  27. infrahub/core/branch/tasks.py +133 -125
  28. infrahub/core/changelog/__init__.py +0 -0
  29. infrahub/core/changelog/diff.py +291 -0
  30. infrahub/core/changelog/models.py +662 -0
  31. infrahub/core/constants/__init__.py +47 -2
  32. infrahub/core/constants/infrahubkind.py +3 -0
  33. infrahub/core/constants/schema.py +2 -0
  34. infrahub/core/constraint/node/runner.py +2 -2
  35. infrahub/core/diff/branch_differ.py +10 -10
  36. infrahub/core/diff/combiner.py +1 -1
  37. infrahub/core/diff/enricher/cardinality_one.py +1 -1
  38. infrahub/core/diff/enricher/hierarchy.py +5 -3
  39. infrahub/core/diff/enricher/labels.py +1 -1
  40. infrahub/core/diff/enricher/path_identifier.py +1 -2
  41. infrahub/core/diff/enricher/summary_counts.py +107 -0
  42. infrahub/core/diff/ipam_diff_parser.py +4 -5
  43. infrahub/core/diff/merger/merger.py +3 -1
  44. infrahub/core/diff/model/diff.py +27 -27
  45. infrahub/core/diff/model/path.py +13 -13
  46. infrahub/core/diff/query/all_conflicts.py +1 -1
  47. infrahub/core/diff/query/artifact.py +1 -1
  48. infrahub/core/diff/query/delete_query.py +1 -1
  49. infrahub/core/diff/query/diff_get.py +1 -1
  50. infrahub/core/diff/query/diff_summary.py +1 -1
  51. infrahub/core/diff/query/field_specifiers.py +1 -1
  52. infrahub/core/diff/query/field_summary.py +1 -1
  53. infrahub/core/diff/query/filters.py +2 -2
  54. infrahub/core/diff/query/get_conflict_query.py +1 -1
  55. infrahub/core/diff/query/has_conflicts_query.py +1 -1
  56. infrahub/core/diff/query/merge.py +3 -3
  57. infrahub/core/diff/query/merge_tracking_id.py +1 -1
  58. infrahub/core/diff/query/roots_metadata.py +1 -1
  59. infrahub/core/diff/query/save.py +3 -3
  60. infrahub/core/diff/query/summary_counts_enricher.py +2 -2
  61. infrahub/core/diff/query/time_range_query.py +1 -1
  62. infrahub/core/diff/query/update_conflict_query.py +1 -1
  63. infrahub/core/diff/query_parser.py +4 -4
  64. infrahub/core/diff/repository/deserializer.py +1 -1
  65. infrahub/core/diff/tasks.py +9 -8
  66. infrahub/core/enums.py +1 -1
  67. infrahub/core/initialization.py +1 -10
  68. infrahub/core/integrity/object_conflict/conflict_recorder.py +1 -1
  69. infrahub/core/ipam/constants.py +3 -4
  70. infrahub/core/ipam/reconciler.py +13 -13
  71. infrahub/core/ipam/tasks.py +2 -3
  72. infrahub/core/ipam/utilization.py +10 -13
  73. infrahub/core/manager.py +52 -47
  74. infrahub/core/merge.py +12 -9
  75. infrahub/core/migrations/__init__.py +1 -3
  76. infrahub/core/migrations/graph/__init__.py +5 -3
  77. infrahub/core/migrations/graph/m001_add_version_to_graph.py +1 -1
  78. infrahub/core/migrations/graph/m002_attribute_is_default.py +2 -2
  79. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +2 -2
  80. infrahub/core/migrations/graph/m004_add_attr_documentation.py +1 -1
  81. infrahub/core/migrations/graph/m005_add_rel_read_only.py +1 -1
  82. infrahub/core/migrations/graph/m006_add_rel_on_delete.py +1 -1
  83. infrahub/core/migrations/graph/m007_add_rel_allow_override.py +1 -1
  84. infrahub/core/migrations/graph/m008_add_human_friendly_id.py +1 -1
  85. infrahub/core/migrations/graph/m009_add_generate_profile_attr.py +1 -1
  86. infrahub/core/migrations/graph/m010_add_generate_profile_attr_generic.py +1 -1
  87. infrahub/core/migrations/graph/m011_remove_profile_relationship_schema.py +2 -2
  88. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -23
  89. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -11
  90. infrahub/core/migrations/graph/m014_remove_index_attr_value.py +2 -2
  91. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
  92. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
  93. infrahub/core/migrations/graph/m017_add_core_profile.py +2 -6
  94. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +3 -3
  95. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +4 -4
  96. infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -3
  97. infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +2 -2
  98. infrahub/core/migrations/graph/m022_add_generate_template_attr.py +48 -0
  99. infrahub/core/migrations/query/attribute_add.py +3 -3
  100. infrahub/core/migrations/query/attribute_rename.py +1 -1
  101. infrahub/core/migrations/query/delete_element_in_schema.py +1 -1
  102. infrahub/core/migrations/query/node_duplicate.py +1 -1
  103. infrahub/core/migrations/query/relationship_duplicate.py +1 -1
  104. infrahub/core/migrations/query/schema_attribute_update.py +3 -3
  105. infrahub/core/migrations/schema/models.py +19 -4
  106. infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
  107. infrahub/core/migrations/schema/node_remove.py +1 -1
  108. infrahub/core/migrations/schema/tasks.py +7 -7
  109. infrahub/core/migrations/shared.py +10 -12
  110. infrahub/core/models.py +13 -14
  111. infrahub/core/node/__init__.py +172 -57
  112. infrahub/core/node/base.py +3 -5
  113. infrahub/core/node/constraints/attribute_uniqueness.py +2 -2
  114. infrahub/core/node/constraints/grouped_uniqueness.py +5 -5
  115. infrahub/core/node/constraints/interface.py +1 -2
  116. infrahub/core/node/delete_validator.py +7 -9
  117. infrahub/core/node/ipam.py +10 -10
  118. infrahub/core/node/permissions.py +7 -7
  119. infrahub/core/node/resource_manager/ip_address_pool.py +6 -6
  120. infrahub/core/node/resource_manager/ip_prefix_pool.py +14 -11
  121. infrahub/core/node/resource_manager/number_pool.py +3 -3
  122. infrahub/core/node/standard.py +3 -5
  123. infrahub/core/path.py +12 -12
  124. infrahub/core/property.py +12 -12
  125. infrahub/core/protocols.py +11 -0
  126. infrahub/core/protocols_base.py +25 -23
  127. infrahub/core/query/__init__.py +35 -38
  128. infrahub/core/query/attribute.py +13 -13
  129. infrahub/core/query/branch.py +5 -5
  130. infrahub/core/query/delete.py +1 -1
  131. infrahub/core/query/diff.py +7 -7
  132. infrahub/core/query/ipam.py +4 -4
  133. infrahub/core/query/node.py +23 -24
  134. infrahub/core/query/relationship.py +143 -46
  135. infrahub/core/query/resource_manager.py +10 -10
  136. infrahub/core/query/standard_node.py +9 -9
  137. infrahub/core/query/subquery.py +9 -9
  138. infrahub/core/query/task.py +3 -3
  139. infrahub/core/query/task_log.py +1 -1
  140. infrahub/core/query/utils.py +5 -5
  141. infrahub/core/registry.py +13 -17
  142. infrahub/core/relationship/constraints/count.py +4 -5
  143. infrahub/core/relationship/constraints/peer_kind.py +4 -5
  144. infrahub/core/relationship/constraints/profiles_kind.py +2 -2
  145. infrahub/core/relationship/model.py +103 -67
  146. infrahub/core/schema/__init__.py +6 -4
  147. infrahub/core/schema/attribute_schema.py +16 -8
  148. infrahub/core/schema/basenode_schema.py +38 -26
  149. infrahub/core/schema/computed_attribute.py +3 -3
  150. infrahub/core/schema/definitions/core/__init__.py +147 -0
  151. infrahub/core/schema/definitions/core/account.py +171 -0
  152. infrahub/core/schema/definitions/core/artifact.py +136 -0
  153. infrahub/core/schema/definitions/core/builtin.py +24 -0
  154. infrahub/core/schema/definitions/core/check.py +68 -0
  155. infrahub/core/schema/definitions/core/core.py +17 -0
  156. infrahub/core/schema/definitions/core/generator.py +100 -0
  157. infrahub/core/schema/definitions/core/graphql_query.py +79 -0
  158. infrahub/core/schema/definitions/core/group.py +108 -0
  159. infrahub/core/schema/definitions/core/ipam.py +193 -0
  160. infrahub/core/schema/definitions/core/lineage.py +19 -0
  161. infrahub/core/schema/definitions/core/menu.py +48 -0
  162. infrahub/core/schema/definitions/core/permission.py +163 -0
  163. infrahub/core/schema/definitions/core/profile.py +18 -0
  164. infrahub/core/schema/definitions/core/propose_change.py +97 -0
  165. infrahub/core/schema/definitions/core/propose_change_comment.py +193 -0
  166. infrahub/core/schema/definitions/core/propose_change_validator.py +328 -0
  167. infrahub/core/schema/definitions/core/repository.py +286 -0
  168. infrahub/core/schema/definitions/core/resource_pool.py +170 -0
  169. infrahub/core/schema/definitions/core/template.py +27 -0
  170. infrahub/core/schema/definitions/core/transform.py +96 -0
  171. infrahub/core/schema/definitions/core/webhook.py +134 -0
  172. infrahub/core/schema/definitions/internal.py +32 -16
  173. infrahub/core/schema/dropdown.py +3 -4
  174. infrahub/core/schema/generated/attribute_schema.py +15 -18
  175. infrahub/core/schema/generated/base_node_schema.py +12 -14
  176. infrahub/core/schema/generated/genericnode_schema.py +5 -0
  177. infrahub/core/schema/generated/node_schema.py +8 -5
  178. infrahub/core/schema/generated/relationship_schema.py +9 -11
  179. infrahub/core/schema/generic_schema.py +6 -2
  180. infrahub/core/schema/manager.py +46 -43
  181. infrahub/core/schema/node_schema.py +6 -2
  182. infrahub/core/schema/profile_schema.py +4 -0
  183. infrahub/core/schema/relationship_schema.py +15 -7
  184. infrahub/core/schema/schema_branch.py +423 -89
  185. infrahub/core/schema/schema_branch_computed.py +41 -4
  186. infrahub/core/schema/template_schema.py +36 -0
  187. infrahub/core/task/task.py +3 -3
  188. infrahub/core/task/user_task.py +21 -19
  189. infrahub/core/timestamp.py +3 -3
  190. infrahub/core/utils.py +12 -12
  191. infrahub/core/validators/__init__.py +1 -3
  192. infrahub/core/validators/aggregated_checker.py +2 -2
  193. infrahub/core/validators/attribute/choices.py +3 -3
  194. infrahub/core/validators/attribute/enum.py +3 -3
  195. infrahub/core/validators/attribute/kind.py +3 -3
  196. infrahub/core/validators/attribute/length.py +3 -3
  197. infrahub/core/validators/attribute/optional.py +3 -3
  198. infrahub/core/validators/attribute/regex.py +3 -3
  199. infrahub/core/validators/attribute/unique.py +3 -3
  200. infrahub/core/validators/checks_runner.py +60 -0
  201. infrahub/core/validators/determiner.py +1 -3
  202. infrahub/core/validators/model.py +1 -3
  203. infrahub/core/validators/models/validate_migration.py +17 -4
  204. infrahub/core/validators/node/attribute.py +2 -2
  205. infrahub/core/validators/node/generate_profile.py +3 -3
  206. infrahub/core/validators/node/hierarchy.py +3 -3
  207. infrahub/core/validators/node/inherit_from.py +2 -2
  208. infrahub/core/validators/node/relationship.py +2 -2
  209. infrahub/core/validators/query.py +1 -1
  210. infrahub/core/validators/relationship/count.py +5 -5
  211. infrahub/core/validators/relationship/optional.py +3 -3
  212. infrahub/core/validators/relationship/peer.py +3 -3
  213. infrahub/core/validators/shared.py +2 -2
  214. infrahub/core/validators/tasks.py +8 -6
  215. infrahub/core/validators/uniqueness/checker.py +5 -6
  216. infrahub/core/validators/uniqueness/index.py +2 -2
  217. infrahub/core/validators/uniqueness/model.py +11 -11
  218. infrahub/core/validators/uniqueness/query.py +1 -1
  219. infrahub/database/__init__.py +19 -23
  220. infrahub/database/memgraph.py +1 -1
  221. infrahub/dependencies/builder/diff/combiner.py +1 -1
  222. infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
  223. infrahub/dependencies/builder/diff/deserializer.py +1 -1
  224. infrahub/dependencies/builder/diff/enricher/summary_counts.py +8 -0
  225. infrahub/dependencies/builder/diff/parent_node_adder.py +1 -1
  226. infrahub/dependencies/component/registry.py +2 -2
  227. infrahub/events/__init__.py +25 -2
  228. infrahub/events/artifact_action.py +64 -0
  229. infrahub/events/branch_action.py +57 -20
  230. infrahub/events/generator.py +71 -0
  231. infrahub/events/group_action.py +103 -0
  232. infrahub/events/models.py +160 -53
  233. infrahub/events/node_action.py +140 -23
  234. infrahub/events/repository_action.py +7 -20
  235. infrahub/events/schema_action.py +18 -10
  236. infrahub/events/utils.py +16 -0
  237. infrahub/events/validator_action.py +55 -0
  238. infrahub/exceptions.py +12 -3
  239. infrahub/generators/models.py +2 -3
  240. infrahub/generators/tasks.py +34 -15
  241. infrahub/git/base.py +10 -12
  242. infrahub/git/constants.py +0 -1
  243. infrahub/git/integrator.py +82 -57
  244. infrahub/git/models.py +101 -9
  245. infrahub/git/repository.py +9 -10
  246. infrahub/git/tasks.py +450 -112
  247. infrahub/git/utils.py +48 -0
  248. infrahub/git/worktree.py +1 -2
  249. infrahub/git_credential/askpass.py +1 -2
  250. infrahub/git_credential/helper.py +2 -3
  251. infrahub/graphql/analyzer.py +572 -11
  252. infrahub/graphql/app.py +47 -41
  253. infrahub/graphql/auth/query_permission_checker/anonymous_checker.py +5 -5
  254. infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +4 -4
  255. infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +4 -4
  256. infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +28 -35
  257. infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -5
  258. infrahub/graphql/context.py +39 -0
  259. infrahub/graphql/enums.py +1 -1
  260. infrahub/graphql/initialization.py +5 -1
  261. infrahub/graphql/loaders/node.py +1 -1
  262. infrahub/graphql/loaders/shared.py +1 -1
  263. infrahub/graphql/manager.py +75 -72
  264. infrahub/graphql/mutations/account.py +20 -13
  265. infrahub/graphql/mutations/artifact_definition.py +18 -14
  266. infrahub/graphql/mutations/branch.py +86 -40
  267. infrahub/graphql/mutations/computed_attribute.py +26 -18
  268. infrahub/graphql/mutations/diff.py +17 -8
  269. infrahub/graphql/mutations/diff_conflict.py +14 -8
  270. infrahub/graphql/mutations/generator.py +83 -0
  271. infrahub/graphql/mutations/graphql_query.py +21 -13
  272. infrahub/graphql/mutations/ipam.py +41 -39
  273. infrahub/graphql/mutations/main.py +226 -66
  274. infrahub/graphql/mutations/menu.py +12 -12
  275. infrahub/graphql/mutations/models.py +2 -4
  276. infrahub/graphql/mutations/node_getter/by_default_filter.py +1 -3
  277. infrahub/graphql/mutations/node_getter/by_hfid.py +1 -3
  278. infrahub/graphql/mutations/node_getter/by_id.py +1 -3
  279. infrahub/graphql/mutations/node_getter/interface.py +1 -2
  280. infrahub/graphql/mutations/proposed_change.py +39 -31
  281. infrahub/graphql/mutations/relationship.py +372 -129
  282. infrahub/graphql/mutations/repository.py +46 -40
  283. infrahub/graphql/mutations/resource_manager.py +26 -26
  284. infrahub/graphql/mutations/schema.py +70 -37
  285. infrahub/graphql/mutations/tasks.py +10 -7
  286. infrahub/graphql/mutations/webhook.py +137 -0
  287. infrahub/graphql/parser.py +5 -5
  288. infrahub/graphql/permissions.py +3 -10
  289. infrahub/graphql/queries/account.py +22 -18
  290. infrahub/graphql/queries/branch.py +6 -4
  291. infrahub/graphql/queries/diff/tree.py +67 -56
  292. infrahub/graphql/queries/event.py +115 -0
  293. infrahub/graphql/queries/internal.py +3 -3
  294. infrahub/graphql/queries/ipam.py +25 -20
  295. infrahub/graphql/queries/relationship.py +13 -12
  296. infrahub/graphql/queries/resource_manager.py +37 -25
  297. infrahub/graphql/queries/search.py +11 -10
  298. infrahub/graphql/queries/status.py +12 -9
  299. infrahub/graphql/queries/task.py +11 -9
  300. infrahub/graphql/resolvers/many_relationship.py +15 -15
  301. infrahub/graphql/resolvers/resolver.py +58 -37
  302. infrahub/graphql/resolvers/single_relationship.py +16 -10
  303. infrahub/graphql/schema.py +4 -0
  304. infrahub/graphql/subscription/__init__.py +1 -1
  305. infrahub/graphql/subscription/events.py +1 -1
  306. infrahub/graphql/subscription/graphql_query.py +8 -8
  307. infrahub/graphql/types/branch.py +2 -2
  308. infrahub/graphql/types/common.py +6 -1
  309. infrahub/graphql/types/context.py +12 -0
  310. infrahub/graphql/types/enums.py +2 -0
  311. infrahub/graphql/types/event.py +167 -0
  312. infrahub/graphql/types/interface.py +2 -2
  313. infrahub/graphql/types/node.py +5 -5
  314. infrahub/graphql/types/permission.py +2 -2
  315. infrahub/graphql/types/relationship.py +3 -3
  316. infrahub/graphql/types/standard_node.py +9 -11
  317. infrahub/graphql/utils.py +30 -184
  318. infrahub/groups/ancestors.py +29 -0
  319. infrahub/groups/parsers.py +107 -0
  320. infrahub/groups/tasks.py +2 -3
  321. infrahub/lock.py +21 -21
  322. infrahub/menu/generator.py +7 -8
  323. infrahub/menu/menu.py +107 -139
  324. infrahub/menu/models.py +121 -20
  325. infrahub/menu/repository.py +111 -0
  326. infrahub/menu/utils.py +5 -8
  327. infrahub/message_bus/__init__.py +11 -13
  328. infrahub/message_bus/messages/__init__.py +1 -25
  329. infrahub/message_bus/messages/check_generator_run.py +3 -3
  330. infrahub/message_bus/messages/event_branch_merge.py +3 -0
  331. infrahub/message_bus/messages/finalize_validator_execution.py +3 -0
  332. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +6 -0
  333. infrahub/message_bus/messages/request_generatordefinition_check.py +2 -0
  334. infrahub/message_bus/messages/request_proposedchange_pipeline.py +2 -0
  335. infrahub/message_bus/messages/send_echo_request.py +1 -1
  336. infrahub/message_bus/operations/__init__.py +4 -15
  337. infrahub/message_bus/operations/check/__init__.py +2 -2
  338. infrahub/message_bus/operations/check/generator.py +2 -3
  339. infrahub/message_bus/operations/event/__init__.py +2 -2
  340. infrahub/message_bus/operations/event/branch.py +7 -3
  341. infrahub/message_bus/operations/event/worker.py +0 -3
  342. infrahub/message_bus/operations/finalize/validator.py +52 -2
  343. infrahub/message_bus/operations/git/file.py +2 -2
  344. infrahub/message_bus/operations/git/repository.py +1 -1
  345. infrahub/message_bus/operations/requests/__init__.py +0 -4
  346. infrahub/message_bus/operations/requests/generator_definition.py +22 -24
  347. infrahub/message_bus/operations/requests/proposed_change.py +39 -20
  348. infrahub/message_bus/operations/send/echo.py +1 -1
  349. infrahub/message_bus/types.py +1 -1
  350. infrahub/permissions/globals.py +15 -0
  351. infrahub/pools/number.py +2 -4
  352. infrahub/pools/prefix.py +29 -165
  353. infrahub/prefect_server/__init__.py +0 -0
  354. infrahub/prefect_server/app.py +18 -0
  355. infrahub/prefect_server/database.py +20 -0
  356. infrahub/prefect_server/events.py +28 -0
  357. infrahub/prefect_server/models.py +46 -0
  358. infrahub/proposed_change/models.py +18 -1
  359. infrahub/proposed_change/tasks.py +204 -53
  360. infrahub/pytest_plugin.py +13 -10
  361. infrahub/server.py +13 -12
  362. infrahub/services/__init__.py +148 -63
  363. infrahub/services/adapters/cache/__init__.py +11 -11
  364. infrahub/services/adapters/cache/nats.py +42 -25
  365. infrahub/services/adapters/cache/redis.py +3 -11
  366. infrahub/services/adapters/event/__init__.py +11 -19
  367. infrahub/services/adapters/http/__init__.py +0 -5
  368. infrahub/services/adapters/http/httpx.py +22 -15
  369. infrahub/services/adapters/message_bus/__init__.py +25 -8
  370. infrahub/services/adapters/message_bus/local.py +9 -7
  371. infrahub/services/adapters/message_bus/nats.py +14 -8
  372. infrahub/services/adapters/message_bus/rabbitmq.py +23 -10
  373. infrahub/services/adapters/workflow/__init__.py +11 -8
  374. infrahub/services/adapters/workflow/local.py +27 -6
  375. infrahub/services/adapters/workflow/worker.py +23 -7
  376. infrahub/services/component.py +43 -40
  377. infrahub/services/protocols.py +7 -7
  378. infrahub/services/scheduler.py +30 -29
  379. infrahub/storage.py +2 -4
  380. infrahub/task_manager/constants.py +1 -1
  381. infrahub/task_manager/event.py +275 -0
  382. infrahub/task_manager/models.py +147 -3
  383. infrahub/task_manager/task.py +1 -1
  384. infrahub/tasks/artifact.py +20 -21
  385. infrahub/tasks/registry.py +1 -1
  386. infrahub/telemetry/__init__.py +0 -0
  387. infrahub/telemetry/constants.py +9 -0
  388. infrahub/telemetry/database.py +86 -0
  389. infrahub/telemetry/models.py +65 -0
  390. infrahub/telemetry/task_manager.py +77 -0
  391. infrahub/telemetry/tasks.py +119 -0
  392. infrahub/telemetry/utils.py +11 -0
  393. infrahub/transformations/tasks.py +5 -7
  394. infrahub/trigger/__init__.py +0 -0
  395. infrahub/trigger/catalogue.py +13 -0
  396. infrahub/trigger/constants.py +1 -0
  397. infrahub/trigger/models.py +118 -0
  398. infrahub/trigger/setup.py +90 -0
  399. infrahub/trigger/tasks.py +36 -0
  400. infrahub/types.py +1 -1
  401. infrahub/utils.py +12 -2
  402. infrahub/validators/__init__.py +0 -0
  403. infrahub/validators/events.py +42 -0
  404. infrahub/validators/tasks.py +41 -0
  405. infrahub/webhook/gather.py +17 -0
  406. infrahub/webhook/models.py +180 -42
  407. infrahub/webhook/tasks.py +149 -203
  408. infrahub/webhook/triggers.py +44 -0
  409. infrahub/workers/infrahub_async.py +38 -27
  410. infrahub/workers/utils.py +63 -0
  411. infrahub/workflows/catalogue.py +98 -71
  412. infrahub/workflows/initialization.py +12 -8
  413. infrahub/workflows/models.py +29 -5
  414. infrahub/workflows/utils.py +11 -2
  415. infrahub_sdk/client.py +19 -0
  416. infrahub_sdk/context.py +13 -0
  417. infrahub_sdk/ctl/branch.py +3 -2
  418. infrahub_sdk/ctl/utils.py +0 -16
  419. infrahub_sdk/exceptions.py +6 -0
  420. infrahub_sdk/generator.py +3 -0
  421. infrahub_sdk/graphql.py +45 -13
  422. infrahub_sdk/node.py +66 -20
  423. infrahub_sdk/protocols.py +21 -8
  424. infrahub_sdk/protocols_base.py +32 -11
  425. infrahub_sdk/schema/__init__.py +14 -2
  426. infrahub_sdk/schema/main.py +7 -0
  427. infrahub_sdk/task/__init__.py +11 -0
  428. infrahub_sdk/task/constants.py +3 -0
  429. infrahub_sdk/task/exceptions.py +25 -0
  430. infrahub_sdk/task/manager.py +551 -0
  431. infrahub_sdk/task/models.py +74 -0
  432. infrahub_sdk/timestamp.py +142 -33
  433. infrahub_sdk/utils.py +29 -1
  434. {infrahub_server-1.1.9.dist-info → infrahub_server-1.2.0.dist-info}/METADATA +8 -6
  435. infrahub_server-1.2.0.dist-info/RECORD +746 -0
  436. infrahub_testcontainers/container.py +5 -6
  437. infrahub_testcontainers/docker-compose.test.yml +2 -2
  438. infrahub_testcontainers/helpers.py +5 -1
  439. infrahub/core/branch/constants.py +0 -2
  440. infrahub/core/schema/definitions/core.py +0 -2275
  441. infrahub/graphql/query.py +0 -52
  442. infrahub/message_bus/messages/check_repository_checkdefinition.py +0 -20
  443. infrahub/message_bus/messages/check_repository_mergeconflicts.py +0 -16
  444. infrahub/message_bus/messages/check_repository_usercheck.py +0 -26
  445. infrahub/message_bus/messages/event_branch_create.py +0 -11
  446. infrahub/message_bus/messages/event_branch_delete.py +0 -11
  447. infrahub/message_bus/messages/event_branch_rebased.py +0 -9
  448. infrahub/message_bus/messages/event_node_mutated.py +0 -15
  449. infrahub/message_bus/messages/event_schema_update.py +0 -9
  450. infrahub/message_bus/messages/request_artifactdefinition_check.py +0 -17
  451. infrahub/message_bus/messages/request_repository_checks.py +0 -12
  452. infrahub/message_bus/messages/request_repository_userchecks.py +0 -18
  453. infrahub/message_bus/operations/check/repository.py +0 -293
  454. infrahub/message_bus/operations/event/node.py +0 -20
  455. infrahub/message_bus/operations/event/schema.py +0 -17
  456. infrahub/message_bus/operations/requests/artifact_definition.py +0 -148
  457. infrahub/message_bus/operations/requests/repository.py +0 -133
  458. infrahub/schema/constants.py +0 -1
  459. infrahub/schema/tasks.py +0 -76
  460. infrahub/services/adapters/database/__init__.py +0 -9
  461. infrahub/tasks/telemetry.py +0 -127
  462. infrahub/webhook/constants.py +0 -3
  463. infrahub_server-1.1.9.dist-info/RECORD +0 -688
  464. /infrahub/{schema → artifacts}/__init__.py +0 -0
  465. {infrahub_server-1.1.9.dist-info → infrahub_server-1.2.0.dist-info}/LICENSE.txt +0 -0
  466. {infrahub_server-1.1.9.dist-info → infrahub_server-1.2.0.dist-info}/WHEEL +0 -0
  467. {infrahub_server-1.1.9.dist-info → infrahub_server-1.2.0.dist-info}/entry_points.txt +0 -0
@@ -7,7 +7,7 @@ from pathlib import Path
7
7
  from typing import TYPE_CHECKING
8
8
 
9
9
  import pytest
10
- from infrahub_sdk.protocols import CoreGeneratorDefinition, CoreProposedChange
10
+ from infrahub_sdk.protocols import CoreArtifactValidator, CoreGeneratorDefinition, CoreProposedChange
11
11
  from prefect import flow, task
12
12
  from prefect.cache_policies import NONE
13
13
  from prefect.client.schemas.objects import (
@@ -17,6 +17,8 @@ from prefect.logging import get_run_logger
17
17
  from prefect.states import Completed, Failed
18
18
 
19
19
  from infrahub import config
20
+ from infrahub.artifacts.models import CheckArtifactCreate
21
+ from infrahub.context import InfrahubContext # noqa: TC001 needed for prefect flow
20
22
  from infrahub.core import registry
21
23
  from infrahub.core.branch import Branch
22
24
  from infrahub.core.branch.tasks import merge_branch
@@ -27,18 +29,21 @@ from infrahub.core.diff.model.path import NodeDiffFieldSummary
27
29
  from infrahub.core.integrity.object_conflict.conflict_recorder import ObjectConflictValidatorRecorder
28
30
  from infrahub.core.protocols import CoreDataCheck, CoreValidator
29
31
  from infrahub.core.protocols import CoreProposedChange as InternalCoreProposedChange
32
+ from infrahub.core.validators.checks_runner import run_checks_and_update_validator
30
33
  from infrahub.core.validators.determiner import ConstraintValidatorDeterminer
31
34
  from infrahub.core.validators.models.validate_migration import SchemaValidateMigrationData
32
35
  from infrahub.core.validators.tasks import schema_validate_migrations
33
36
  from infrahub.dependencies.registry import get_component_registry
34
37
  from infrahub.exceptions import MergeFailedError
35
38
  from infrahub.generators.models import ProposedChangeGeneratorDefinition
39
+ from infrahub.git.models import TriggerRepositoryInternalChecks, TriggerRepositoryUserChecks
36
40
  from infrahub.git.repository import get_initialized_repo
37
41
  from infrahub.log import get_logger
38
42
  from infrahub.message_bus import InfrahubMessage, messages
39
43
  from infrahub.message_bus.operations.requests.proposed_change import DefinitionSelect
40
44
  from infrahub.proposed_change.constants import ProposedChangeState
41
45
  from infrahub.proposed_change.models import (
46
+ RequestArtifactDefinitionCheck,
42
47
  RequestProposedChangeDataIntegrity,
43
48
  RequestProposedChangeRepositoryChecks,
44
49
  RequestProposedChangeRunGenerators,
@@ -46,8 +51,14 @@ from infrahub.proposed_change.models import (
46
51
  RequestProposedChangeUserTests,
47
52
  )
48
53
  from infrahub.pytest_plugin import InfrahubBackendPlugin
49
- from infrahub.services import services
50
- from infrahub.workflows.catalogue import COMPUTED_ATTRIBUTE_SETUP_PYTHON, REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS
54
+ from infrahub.services import InfrahubServices # noqa: TC001 needed for prefect flow
55
+ from infrahub.validators.tasks import start_validator
56
+ from infrahub.workflows.catalogue import (
57
+ GIT_REPOSITORIES_CHECK_ARTIFACT_CREATE,
58
+ GIT_REPOSITORY_INTERNAL_CHECKS_TRIGGER,
59
+ GIT_REPOSITORY_USER_CHECKS_TRIGGER,
60
+ REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
61
+ )
51
62
  from infrahub.workflows.utils import add_tags
52
63
 
53
64
  if TYPE_CHECKING:
@@ -60,10 +71,10 @@ if TYPE_CHECKING:
60
71
 
61
72
  async def _proposed_change_transition_state(
62
73
  state: ProposedChangeState,
74
+ service: InfrahubServices,
63
75
  proposed_change: InternalCoreProposedChange | None = None,
64
76
  proposed_change_id: str | None = None,
65
77
  ) -> None:
66
- service = services.service
67
78
  async with service.database.start_session() as db:
68
79
  if proposed_change is None and proposed_change_id:
69
80
  proposed_change = await registry.manager.get_one(
@@ -96,8 +107,12 @@ async def _proposed_change_transition_state(
96
107
  # on_crashed=[proposed_change_transition_open], # type: ignore
97
108
  # on_cancellation=[proposed_change_transition_open], # type: ignore
98
109
  )
99
- async def merge_proposed_change(proposed_change_id: str, proposed_change_name: str) -> State: # pylint: disable=unused-argument
100
- service = services.service
110
+ async def merge_proposed_change(
111
+ proposed_change_id: str,
112
+ proposed_change_name: str, # noqa: ARG001
113
+ context: InfrahubContext,
114
+ service: InfrahubServices,
115
+ ) -> State:
101
116
  log = get_run_logger()
102
117
 
103
118
  await add_tags(nodes=[proposed_change_id])
@@ -118,14 +133,16 @@ async def merge_proposed_change(proposed_change_id: str, proposed_change_name: s
118
133
  and validation.conclusion.value.value != ValidatorConclusion.SUCCESS.value
119
134
  ):
120
135
  # Ignoring Data integrity checks as they are handled again later
121
- await _proposed_change_transition_state(proposed_change=proposed_change, state=ProposedChangeState.OPEN)
136
+ await _proposed_change_transition_state(
137
+ proposed_change=proposed_change, state=ProposedChangeState.OPEN, service=service
138
+ )
122
139
  return Failed(message="Unable to merge proposed change containing failing checks")
123
140
  if validator_kind == InfrahubKind.DATAVALIDATOR:
124
141
  data_checks = await validation.checks.get_peers(db=db, peer_type=CoreDataCheck)
125
142
  for check in data_checks.values():
126
143
  if check.conflicts.value and not check.keep_branch.value:
127
144
  await _proposed_change_transition_state(
128
- proposed_change=proposed_change, state=ProposedChangeState.OPEN
145
+ proposed_change=proposed_change, state=ProposedChangeState.OPEN, service=service
129
146
  )
130
147
  return Failed(
131
148
  message="Data conflicts found on branch and missing decisions about what branch to keep"
@@ -133,15 +150,20 @@ async def merge_proposed_change(proposed_change_id: str, proposed_change_name: s
133
150
 
134
151
  log.info("Proposed change is eligible to be merged")
135
152
  try:
136
- await merge_branch(branch=source_branch.name)
153
+ await merge_branch(
154
+ branch=source_branch.name, context=context, service=service, proposed_change_id=proposed_change_id
155
+ )
137
156
  except MergeFailedError as exc:
138
- await _proposed_change_transition_state(proposed_change=proposed_change, state=ProposedChangeState.OPEN)
157
+ await _proposed_change_transition_state(
158
+ proposed_change=proposed_change, state=ProposedChangeState.OPEN, service=service
159
+ )
139
160
  return Failed(message=f"Merge failure when trying to merge {exc.message}")
140
161
 
141
162
  log.info(f"Branch {source_branch.name} has been merged successfully")
142
163
 
143
- await _proposed_change_transition_state(proposed_change=proposed_change, state=ProposedChangeState.MERGED)
144
- await service.workflow.submit_workflow(workflow=COMPUTED_ATTRIBUTE_SETUP_PYTHON)
164
+ await _proposed_change_transition_state(
165
+ proposed_change=proposed_change, state=ProposedChangeState.MERGED, service=service
166
+ )
145
167
  return Completed(message="proposed change merged successfully")
146
168
 
147
169
 
@@ -150,9 +172,7 @@ async def merge_proposed_change(proposed_change_id: str, proposed_change_name: s
150
172
  flow_run_name="Cancel all proposed change associated with branch {branch_name}",
151
173
  description="Cancel all Proposed change associated with a branch.",
152
174
  )
153
- async def cancel_proposed_changes_branch(branch_name: str) -> None:
154
- service = services.service
155
-
175
+ async def cancel_proposed_changes_branch(branch_name: str, service: InfrahubServices) -> None:
156
176
  await add_tags(branches=[branch_name])
157
177
 
158
178
  proposed_changed_opened = await service.client.filters(
@@ -169,13 +189,11 @@ async def cancel_proposed_changes_branch(branch_name: str) -> None:
169
189
  )
170
190
 
171
191
  for proposed_change in proposed_changed_opened + proposed_changed_closed:
172
- await cancel_proposed_change(proposed_change=proposed_change)
192
+ await cancel_proposed_change(proposed_change=proposed_change, service=service)
173
193
 
174
194
 
175
- @task(name="Cancel a propose change", description="Cancel a propose change", cache_policy=NONE)
176
- async def cancel_proposed_change(proposed_change: CoreProposedChange) -> None:
177
- service = services.service
178
-
195
+ @task(name="Cancel a propose change", description="Cancel a propose change", cache_policy=NONE) # type: ignore[arg-type]
196
+ async def cancel_proposed_change(proposed_change: CoreProposedChange, service: InfrahubServices) -> None:
179
197
  await add_tags(nodes=[proposed_change.id])
180
198
  log = get_run_logger()
181
199
 
@@ -189,11 +207,12 @@ async def cancel_proposed_change(proposed_change: CoreProposedChange) -> None:
189
207
  name="proposed-changed-data-integrity",
190
208
  flow_run_name="Triggers data integrity check",
191
209
  )
192
- async def run_proposed_change_data_integrity_check(model: RequestProposedChangeDataIntegrity) -> None:
210
+ async def run_proposed_change_data_integrity_check(
211
+ model: RequestProposedChangeDataIntegrity, service: InfrahubServices
212
+ ) -> None:
193
213
  """Triggers a data integrity validation check on the provided proposed change to start."""
194
214
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
195
215
 
196
- service = services.service
197
216
  async with service.database.start_transaction() as dbt:
198
217
  destination_branch = await registry.get_branch(db=dbt, branch=model.destination_branch)
199
218
  source_branch = await registry.get_branch(db=dbt, branch=model.source_branch)
@@ -207,8 +226,9 @@ async def run_proposed_change_data_integrity_check(model: RequestProposedChangeD
207
226
  name="proposed-changed-run-generator",
208
227
  flow_run_name="Run generators",
209
228
  )
210
- async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
211
- service = services.service
229
+ async def run_generators(
230
+ model: RequestProposedChangeRunGenerators, context: InfrahubContext, service: InfrahubServices
231
+ ) -> None:
212
232
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change], db_change=True)
213
233
 
214
234
  generators = await service.client.filters(
@@ -256,6 +276,7 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
256
276
 
257
277
  if select:
258
278
  msg = messages.RequestGeneratorDefinitionCheck(
279
+ context=context,
259
280
  generator_definition=generator_definition,
260
281
  branch_diff=model.branch_diff,
261
282
  proposed_change=model.proposed_change,
@@ -264,12 +285,13 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
264
285
  destination_branch=model.destination_branch,
265
286
  )
266
287
  msg.assign_meta(parent=model)
267
- await service.send(message=msg)
288
+ await service.message_bus.send(message=msg)
268
289
 
269
290
  next_messages: list[InfrahubMessage] = []
270
291
  if model.refresh_artifacts:
271
292
  next_messages.append(
272
293
  messages.RequestProposedChangeRefreshArtifacts(
294
+ context=context,
273
295
  proposed_change=model.proposed_change,
274
296
  source_branch=model.source_branch,
275
297
  source_branch_sync_with_git=model.source_branch_sync_with_git,
@@ -287,12 +309,14 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
287
309
  branch_diff=model.branch_diff,
288
310
  )
289
311
  await service.workflow.submit_workflow(
290
- workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS, parameters={"model": model_proposed_change_repo_checks}
312
+ workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
313
+ context=context,
314
+ parameters={"model": model_proposed_change_repo_checks},
291
315
  )
292
316
 
293
317
  for next_msg in next_messages:
294
318
  next_msg.assign_meta(parent=model)
295
- await service.send(message=next_msg)
319
+ await service.message_bus.send(message=next_msg)
296
320
 
297
321
 
298
322
  @flow(
@@ -300,11 +324,10 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
300
324
  flow_run_name="Process schema integrity",
301
325
  )
302
326
  async def run_proposed_change_schema_integrity_check(
303
- model: RequestProposedChangeSchemaIntegrity,
327
+ model: RequestProposedChangeSchemaIntegrity, service: InfrahubServices
304
328
  ) -> None:
305
329
  # For now, we retrieve the latest schema for each branch from the registry
306
330
  # In the future it would be good to generate the object SchemaUpdateValidationResult from message.branch_diff
307
- service = services.service
308
331
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
309
332
 
310
333
  source_schema = registry.schema.get_schema_branch(name=model.source_branch).duplicate()
@@ -331,7 +354,8 @@ async def run_proposed_change_schema_integrity_check(
331
354
  responses = await schema_validate_migrations(
332
355
  message=SchemaValidateMigrationData(
333
356
  branch=source_branch, schema_branch=candidate_schema, constraints=list(constraints)
334
- )
357
+ ),
358
+ service=service,
335
359
  )
336
360
 
337
361
  # TODO we need to report a failure if an error happened during the execution of a validator
@@ -393,48 +417,50 @@ async def _get_proposed_change_schema_integrity_constraints(
393
417
  name="proposed-changed-repository-checks",
394
418
  flow_run_name="Process user defined checks",
395
419
  )
396
- async def repository_checks(model: RequestProposedChangeRepositoryChecks) -> None:
397
- service = services.service
420
+ async def repository_checks(
421
+ model: RequestProposedChangeRepositoryChecks, service: InfrahubServices, context: InfrahubContext
422
+ ) -> None:
398
423
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
399
424
 
400
- events: list[InfrahubMessage] = []
401
425
  for repository in model.branch_diff.repositories:
402
426
  if (
403
427
  model.source_branch_sync_with_git
404
428
  and not repository.read_only
405
429
  and repository.internal_status == RepositoryInternalStatus.ACTIVE.value
406
430
  ):
407
- events.append(
408
- messages.RequestRepositoryChecks(
409
- proposed_change=model.proposed_change,
410
- repository=repository.repository_id,
411
- source_branch=model.source_branch,
412
- target_branch=model.destination_branch,
413
- )
414
- )
415
-
416
- events.append(
417
- messages.RequestRepositoryUserChecks(
431
+ trigger_internal_checks_model = TriggerRepositoryInternalChecks(
418
432
  proposed_change=model.proposed_change,
419
- repository_id=repository.repository_id,
420
- repository_name=repository.repository_name,
433
+ repository=repository.repository_id,
421
434
  source_branch=model.source_branch,
422
- source_branch_sync_with_git=model.source_branch_sync_with_git,
423
435
  target_branch=model.destination_branch,
424
- branch_diff=model.branch_diff,
425
436
  )
437
+ await service.workflow.submit_workflow(
438
+ workflow=GIT_REPOSITORY_INTERNAL_CHECKS_TRIGGER,
439
+ context=context,
440
+ parameters={"model": trigger_internal_checks_model},
441
+ )
442
+
443
+ trigger_user_checks_model = TriggerRepositoryUserChecks(
444
+ proposed_change=model.proposed_change,
445
+ repository_id=repository.repository_id,
446
+ repository_name=repository.repository_name,
447
+ source_branch=model.source_branch,
448
+ source_branch_sync_with_git=model.source_branch_sync_with_git,
449
+ target_branch=model.destination_branch,
450
+ branch_diff=model.branch_diff,
451
+ )
452
+ await service.workflow.submit_workflow(
453
+ workflow=GIT_REPOSITORY_USER_CHECKS_TRIGGER,
454
+ context=context,
455
+ parameters={"model": trigger_user_checks_model},
426
456
  )
427
- for event in events:
428
- event.assign_meta(parent=model)
429
- await service.send(message=event)
430
457
 
431
458
 
432
459
  @flow(
433
460
  name="proposed-changed-user-tests",
434
461
  flow_run_name="Run unit tests in repositories",
435
462
  )
436
- async def run_proposed_change_user_tests(model: RequestProposedChangeUserTests) -> None:
437
- service = services.service
463
+ async def run_proposed_change_user_tests(model: RequestProposedChangeUserTests, service: InfrahubServices) -> None:
438
464
  log = get_run_logger()
439
465
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
440
466
  proposed_change = await service.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=model.proposed_change)
@@ -493,3 +519,128 @@ async def run_proposed_change_user_tests(model: RequestProposedChangeUserTests)
493
519
 
494
520
  return_code = await asyncio.to_thread(_execute, worktree_directory, repository, proposed_change)
495
521
  log.info(msg=f"repository_tests_completed return_code={return_code}")
522
+
523
+
524
+ @flow(
525
+ name="artifacts-generation-validation",
526
+ flow_run_name="Validating generation of artifacts for {model.artifact_definition.definition_name}",
527
+ )
528
+ async def validate_artifacts_generation(model: RequestArtifactDefinitionCheck, service: InfrahubServices) -> None:
529
+ await add_tags(branches=[model.source_branch], nodes=[model.proposed_change], db_change=True)
530
+
531
+ log = get_run_logger()
532
+ artifact_definition = await service.client.get(
533
+ kind=InfrahubKind.ARTIFACTDEFINITION,
534
+ id=model.artifact_definition.definition_id,
535
+ branch=model.source_branch,
536
+ )
537
+ proposed_change = await service.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=model.proposed_change)
538
+
539
+ validator_name = f"Artifact Validator: {model.artifact_definition.definition_name}"
540
+
541
+ await proposed_change.validations.fetch()
542
+
543
+ previous_validator: CoreArtifactValidator | None = None
544
+ for relationship in proposed_change.validations.peers:
545
+ existing_validator = relationship.peer
546
+ if (
547
+ existing_validator.typename == InfrahubKind.ARTIFACTVALIDATOR
548
+ and existing_validator.definition.id == model.artifact_definition.definition_id
549
+ ):
550
+ previous_validator = existing_validator
551
+
552
+ validator = await start_validator(
553
+ service=service,
554
+ validator=previous_validator,
555
+ validator_type=CoreArtifactValidator,
556
+ proposed_change=model.proposed_change,
557
+ data={
558
+ "label": validator_name,
559
+ "definition": model.artifact_definition.definition_id,
560
+ },
561
+ context=model.context,
562
+ )
563
+
564
+ await artifact_definition.targets.fetch()
565
+ group = artifact_definition.targets.peer
566
+ await group.members.fetch()
567
+
568
+ existing_artifacts = await service.client.filters(
569
+ kind=InfrahubKind.ARTIFACT,
570
+ definition__ids=[model.artifact_definition.definition_id],
571
+ include=["object"],
572
+ branch=model.source_branch,
573
+ )
574
+ artifacts_by_member = {}
575
+ for artifact in existing_artifacts:
576
+ artifacts_by_member[artifact.object.peer.id] = artifact.id
577
+
578
+ repository = model.branch_diff.get_repository(repository_id=model.artifact_definition.repository_id)
579
+ impacted_artifacts = model.branch_diff.get_subscribers_ids(kind=InfrahubKind.ARTIFACT)
580
+
581
+ checks = []
582
+
583
+ for relationship in group.members.peers:
584
+ member = relationship.peer
585
+ artifact_id = artifacts_by_member.get(member.id)
586
+ if _should_render_artifact(
587
+ artifact_id=artifact_id,
588
+ managed_branch=model.source_branch_sync_with_git,
589
+ impacted_artifacts=impacted_artifacts,
590
+ ):
591
+ log.info(f"Trigger Artifact processing for {member.display_label}")
592
+
593
+ check_model = CheckArtifactCreate(
594
+ context=model.context,
595
+ artifact_name=model.artifact_definition.artifact_name,
596
+ artifact_id=artifact_id,
597
+ artifact_definition=model.artifact_definition.definition_id,
598
+ commit=repository.source_commit,
599
+ content_type=model.artifact_definition.content_type,
600
+ transform_type=model.artifact_definition.transform_kind,
601
+ transform_location=model.artifact_definition.transform_location,
602
+ repository_id=repository.repository_id,
603
+ repository_name=repository.repository_name,
604
+ repository_kind=repository.kind,
605
+ branch_name=model.source_branch,
606
+ query=model.artifact_definition.query_name,
607
+ variables=member.extract(params=artifact_definition.parameters.value),
608
+ target_id=member.id,
609
+ target_kind=member.get_kind(),
610
+ target_name=member.display_label,
611
+ timeout=model.artifact_definition.timeout,
612
+ validator_id=validator.id,
613
+ )
614
+
615
+ checks.append(
616
+ service.workflow.execute_workflow(
617
+ workflow=GIT_REPOSITORIES_CHECK_ARTIFACT_CREATE,
618
+ parameters={"model": check_model},
619
+ expected_return=ValidatorConclusion,
620
+ )
621
+ )
622
+
623
+ await run_checks_and_update_validator(
624
+ checks=checks,
625
+ validator=validator,
626
+ proposed_change_id=model.proposed_change,
627
+ context=model.context,
628
+ service=service,
629
+ )
630
+
631
+
632
+ def _should_render_artifact(artifact_id: str | None, managed_branch: bool, impacted_artifacts: list[str]) -> bool: # noqa: ARG001
633
+ """Returns a boolean to indicate if an artifact should be generated or not.
634
+ Will return true if:
635
+ * The artifact_id wasn't set which could be that it's a new object that doesn't have a previous artifact
636
+ * The source brance is not data only which would indicate that it could contain updates in git to the transform
637
+ * The artifact_id exists in the impacted_artifacts list
638
+ Will return false if:
639
+ * The source branch is a data only branch and the artifact_id exists and is not in the impacted list
640
+ """
641
+
642
+ # if not artifact_id or managed_branch:
643
+ # return True
644
+ # return artifact_id in impacted_artifacts
645
+ # Temporary workaround tracked in https://github.com/opsmill/infrahub/issues/4991
646
+ return True
infrahub/pytest_plugin.py CHANGED
@@ -1,9 +1,7 @@
1
- from typing import Optional
2
-
1
+ import pytest
3
2
  from infrahub_sdk.client import Config as InfrahubClientConfig
4
3
  from infrahub_sdk.client import InfrahubClientSync
5
4
  from infrahub_sdk.node import InfrahubNodeSync
6
- from pytest import Config, Item, Session, TestReport
7
5
 
8
6
  from infrahub.core.constants import InfrahubKind
9
7
  from infrahub.core.timestamp import Timestamp
@@ -52,7 +50,12 @@ class InfrahubBackendPlugin:
52
50
 
53
51
  return validator, True
54
52
 
55
- def pytest_collection_modifyitems(self, session: Session, config: Config, items: list[Item]) -> None: # pylint: disable=unused-argument
53
+ def pytest_collection_modifyitems(
54
+ self,
55
+ session: pytest.Session, # noqa: ARG002
56
+ config: pytest.Config, # noqa: ARG002
57
+ items: list[pytest.Item],
58
+ ) -> None:
56
59
  """This function is called after item collection and gives the opportunity to work on the collection before sending the items for testing.
57
60
 
58
61
  All items without an "infrahub" marker will be discarded. Items will also be re-ordered to be run in a specific order:
@@ -64,7 +67,7 @@ class InfrahubBackendPlugin:
64
67
  """
65
68
  filtered_items = [i for i in items if i.get_closest_marker("infrahub")]
66
69
 
67
- def sort_key(item: Item) -> tuple[int, int]:
70
+ def sort_key(item: pytest.Item) -> tuple[int, int]:
68
71
  type_cost = 99
69
72
  for marker_name, priority in ORDER_TYPE_MAP.items():
70
73
  if item.get_closest_marker(marker_name):
@@ -82,7 +85,7 @@ class InfrahubBackendPlugin:
82
85
  filtered_items.sort(key=sort_key)
83
86
  items[:] = filtered_items
84
87
 
85
- def pytest_collection_finish(self, session: Session) -> None: # pylint: disable=unused-argument
88
+ def pytest_collection_finish(self, session: pytest.Session) -> None: # noqa: ARG002
86
89
  """This function is called when tests have been collected and modified, meaning they are ready to be run."""
87
90
  self.proposed_change = self.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=self.proposed_change_id)
88
91
  self.proposed_change.validations.fetch()
@@ -95,7 +98,7 @@ class InfrahubBackendPlugin:
95
98
  check = relationship.peer
96
99
  self.checks[check.origin.value] = check
97
100
 
98
- def pytest_runtestloop(self, session: Session) -> Optional[object]: # pylint: disable=unused-argument,useless-return
101
+ def pytest_runtestloop(self, session: pytest.Session) -> object | None: # noqa: ARG002
99
102
  """This function is called when the test loop is being run."""
100
103
  self.validator.conclusion.value = "unknown"
101
104
  self.validator.state.value = "in_progress"
@@ -104,7 +107,7 @@ class InfrahubBackendPlugin:
104
107
 
105
108
  return None
106
109
 
107
- def pytest_runtest_setup(self, item: Item) -> None:
110
+ def pytest_runtest_setup(self, item: pytest.Item) -> None:
108
111
  """Create a StandardCheck for each test item to later record its details.
109
112
 
110
113
  If a check already exists, reset it to its default values.
@@ -132,7 +135,7 @@ class InfrahubBackendPlugin:
132
135
 
133
136
  check.save()
134
137
 
135
- def pytest_runtest_logreport(self, report: TestReport) -> None:
138
+ def pytest_runtest_logreport(self, report: pytest.TestReport) -> None:
136
139
  """This function is called 3 times per test: setup, call, teardown."""
137
140
  if report.when != "call":
138
141
  return
@@ -144,7 +147,7 @@ class InfrahubBackendPlugin:
144
147
  # Workaround for https://github.com/opsmill/infrahub/issues/2184
145
148
  check.update(do_full_update=True)
146
149
 
147
- def pytest_sessionfinish(self, session: Session) -> None: # pylint: disable=unused-argument
150
+ def pytest_sessionfinish(self, session: pytest.Session) -> None: # noqa: ARG002
148
151
  """Set the final RepositoryValidator details after completing the test session."""
149
152
  conclusion = "success"
150
153
 
infrahub/server.py CHANGED
@@ -14,7 +14,7 @@ from fastapi.middleware.gzip import GZipMiddleware
14
14
  from fastapi.responses import RedirectResponse
15
15
  from fastapi.staticfiles import StaticFiles
16
16
  from fastapi.templating import Jinja2Templates
17
- from infrahub_sdk.timestamp import TimestampFormatError
17
+ from infrahub_sdk.exceptions import TimestampFormatError
18
18
  from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
19
19
  from opentelemetry.trace import Span
20
20
  from pydantic import ValidationError
@@ -33,7 +33,7 @@ from infrahub.graphql.api.endpoints import router as graphql_router
33
33
  from infrahub.lock import initialize_lock
34
34
  from infrahub.log import clear_log_context, get_logger, set_log_data
35
35
  from infrahub.middleware import InfrahubCORSMiddleware
36
- from infrahub.services import InfrahubServices, services
36
+ from infrahub.services import InfrahubServices
37
37
  from infrahub.services.adapters.cache.nats import NATSCache
38
38
  from infrahub.services.adapters.cache.redis import RedisCache
39
39
  from infrahub.services.adapters.message_bus.nats import NATSMessageBus
@@ -70,26 +70,27 @@ async def app_initialization(application: FastAPI, enable_scheduler: bool = True
70
70
  if config.SETTINGS.workflow.driver == config.WorkflowDriver.WORKER
71
71
  else WorkflowLocalExecution()
72
72
  )
73
-
73
+ component_type = ComponentType.API_SERVER
74
74
  message_bus = config.OVERRIDE.message_bus or (
75
- NATSMessageBus() if config.SETTINGS.broker.driver == config.BrokerDriver.NATS else RabbitMQMessageBus()
75
+ await NATSMessageBus.new(component_type=component_type)
76
+ if config.SETTINGS.broker.driver == config.BrokerDriver.NATS
77
+ else await RabbitMQMessageBus.new(component_type=component_type)
76
78
  )
77
79
  cache = config.OVERRIDE.cache or (
78
- NATSCache() if config.SETTINGS.cache.driver == config.CacheDriver.NATS else RedisCache()
80
+ await NATSCache.new() if config.SETTINGS.cache.driver == config.CacheDriver.NATS else RedisCache()
79
81
  )
80
- service = InfrahubServices(
82
+ service = await InfrahubServices.new(
81
83
  cache=cache,
82
84
  database=database,
83
85
  message_bus=message_bus,
84
86
  workflow=workflow,
85
- component_type=ComponentType.API_SERVER,
87
+ component_type=component_type,
86
88
  )
87
- await service.initialize()
88
89
  initialize_lock(service=service)
89
90
  # We must initialize DB after initialize lock and initialize lock depends on cache initialization
90
91
  async with application.state.db.start_session() as db:
91
92
  await initialization(db=db)
92
- services.prepare(service=service)
93
+
93
94
  application.state.service = service
94
95
  application.state.response_delay = config.SETTINGS.miscellaneous.response_delay
95
96
  if enable_scheduler:
@@ -97,7 +98,7 @@ async def app_initialization(application: FastAPI, enable_scheduler: bool = True
97
98
 
98
99
 
99
100
  async def shutdown(application: FastAPI) -> None:
100
- await services.service.shutdown()
101
+ await application.state.service.shutdown()
101
102
  await application.state.db.close()
102
103
 
103
104
 
@@ -118,7 +119,7 @@ app = FastAPI(
118
119
  )
119
120
 
120
121
 
121
- def server_request_hook(span: Span, scope: dict) -> None: # pylint: disable=unused-argument
122
+ def server_request_hook(span: Span, scope: dict) -> None: # noqa: ARG001
122
123
  if span and span.is_recording():
123
124
  span.set_attribute("worker", WORKER_IDENTITY)
124
125
 
@@ -217,5 +218,5 @@ async def documentation() -> RedirectResponse:
217
218
 
218
219
 
219
220
  @app.get("/{rest_of_path:path}", include_in_schema=False)
220
- async def react_app(req: Request, rest_of_path: str) -> Response: # pylint: disable=unused-argument
221
+ async def react_app(req: Request, rest_of_path: str) -> Response: # noqa: ARG001
221
222
  return templates.TemplateResponse("index.html", {"request": req})