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
@@ -0,0 +1,46 @@
1
+ from typing import TYPE_CHECKING, Sequence, cast
2
+
3
+ from prefect.server.database import PrefectDBInterface, db_injector
4
+ from prefect.server.events.filters import EventFilter, EventNameFilter, EventOrder, EventRelatedFilter
5
+ from prefect.server.events.schemas.events import ReceivedEvent
6
+ from prefect.server.utilities.schemas import PrefectBaseModel
7
+ from pydantic import BaseModel, Field
8
+
9
+ if TYPE_CHECKING:
10
+ from sqlalchemy.sql.expression import ColumnExpressionArgument
11
+
12
+
13
+ class InfrahubEventFilter(EventFilter):
14
+ matching_related: list[EventRelatedFilter] = Field(default_factory=list)
15
+
16
+ def set_prefix(self) -> None:
17
+ if self.event:
18
+ if self.event.prefix is not None and "infrahub." not in self.event.prefix:
19
+ self.event.prefix.append("infrahub.")
20
+ else:
21
+ self.event = EventNameFilter(prefix=["infrahub."], name=[], exclude_prefix=None, exclude_name=None)
22
+
23
+ @db_injector
24
+ def build_where_clauses(self, db: PrefectDBInterface) -> Sequence["ColumnExpressionArgument[bool]"]:
25
+ result = cast(list["ColumnExpressionArgument[bool]"], super().build_where_clauses())
26
+ top_level_filter = self._scoped_event_resources(db)
27
+ for matching_related in self.matching_related:
28
+ matching_related._top_level_filter = top_level_filter
29
+ result.extend(matching_related.build_where_clauses())
30
+
31
+ return result
32
+
33
+ @classmethod
34
+ def default(cls) -> "InfrahubEventFilter":
35
+ return cls(event=None, any_resource=None, resource=None, related=None, order=EventOrder.DESC)
36
+
37
+
38
+ class InfrahubEventPage(PrefectBaseModel):
39
+ events: list[ReceivedEvent] = Field(..., description="The Events matching the query")
40
+ total: int = Field(..., description="The total number of matching Events")
41
+
42
+
43
+ class InfrahubEventfilterInput(BaseModel):
44
+ limit: int = Field(default=50)
45
+ filter: InfrahubEventFilter = Field(default_factory=InfrahubEventFilter.default)
46
+ offset: int | None = Field(default=None)
@@ -1,6 +1,8 @@
1
- from pydantic import Field
1
+ from pydantic import BaseModel, ConfigDict, Field
2
2
 
3
+ from infrahub.context import InfrahubContext
3
4
  from infrahub.message_bus.messages.proposed_change.base_with_diff import BaseProposedChangeWithDiffMessage
5
+ from infrahub.message_bus.types import ProposedChangeArtifactDefinition, ProposedChangeBranchDiff
4
6
 
5
7
 
6
8
  class RequestProposedChangeDataIntegrity(BaseProposedChangeWithDiffMessage):
@@ -26,3 +28,18 @@ class RequestProposedChangeSchemaIntegrity(BaseProposedChangeWithDiffMessage):
26
28
 
27
29
  class RequestProposedChangeUserTests(BaseProposedChangeWithDiffMessage):
28
30
  """Sent trigger to run tests (smoke, units, integrations) for a proposed change."""
31
+
32
+
33
+ class RequestArtifactDefinitionCheck(BaseModel):
34
+ """Sent to validate the generation of artifacts in relation to a proposed change."""
35
+
36
+ model_config = ConfigDict(arbitrary_types_allowed=True)
37
+
38
+ artifact_definition: ProposedChangeArtifactDefinition = Field(..., description="The Artifact Definition")
39
+ branch_diff: ProposedChangeBranchDiff = Field(..., description="The calculated diff between the two branches")
40
+ proposed_change: str = Field(..., description="The unique ID of the Proposed Change")
41
+ source_branch: str = Field(..., description="The source branch")
42
+ source_branch_sync_with_git: bool = Field(..., description="Indicates if the source branch should sync with git")
43
+ destination_branch: str = Field(..., description="The target branch")
44
+
45
+ context: InfrahubContext = Field(..., description="The context of the task")
@@ -17,28 +17,33 @@ 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
23
- from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus, ValidatorConclusion
25
+ from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus, ValidatorConclusion, ValidatorState
24
26
  from infrahub.core.diff.coordinator import DiffCoordinator
25
27
  from infrahub.core.diff.model.diff import DiffElementType, SchemaConflict
26
28
  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.workflows.catalogue import (
56
+ COMPUTED_ATTRIBUTE_SETUP_PYTHON,
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,19 @@ 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(branch=source_branch.name, context=context, service=service)
137
154
  except MergeFailedError as exc:
138
- await _proposed_change_transition_state(proposed_change=proposed_change, state=ProposedChangeState.OPEN)
155
+ await _proposed_change_transition_state(
156
+ proposed_change=proposed_change, state=ProposedChangeState.OPEN, service=service
157
+ )
139
158
  return Failed(message=f"Merge failure when trying to merge {exc.message}")
140
159
 
141
160
  log.info(f"Branch {source_branch.name} has been merged successfully")
142
161
 
143
- await _proposed_change_transition_state(proposed_change=proposed_change, state=ProposedChangeState.MERGED)
144
- await service.workflow.submit_workflow(workflow=COMPUTED_ATTRIBUTE_SETUP_PYTHON)
162
+ await _proposed_change_transition_state(
163
+ proposed_change=proposed_change, state=ProposedChangeState.MERGED, service=service
164
+ )
165
+ await service.workflow.submit_workflow(workflow=COMPUTED_ATTRIBUTE_SETUP_PYTHON, context=context)
145
166
  return Completed(message="proposed change merged successfully")
146
167
 
147
168
 
@@ -150,9 +171,7 @@ async def merge_proposed_change(proposed_change_id: str, proposed_change_name: s
150
171
  flow_run_name="Cancel all proposed change associated with branch {branch_name}",
151
172
  description="Cancel all Proposed change associated with a branch.",
152
173
  )
153
- async def cancel_proposed_changes_branch(branch_name: str) -> None:
154
- service = services.service
155
-
174
+ async def cancel_proposed_changes_branch(branch_name: str, service: InfrahubServices) -> None:
156
175
  await add_tags(branches=[branch_name])
157
176
 
158
177
  proposed_changed_opened = await service.client.filters(
@@ -169,13 +188,11 @@ async def cancel_proposed_changes_branch(branch_name: str) -> None:
169
188
  )
170
189
 
171
190
  for proposed_change in proposed_changed_opened + proposed_changed_closed:
172
- await cancel_proposed_change(proposed_change=proposed_change)
173
-
191
+ await cancel_proposed_change(proposed_change=proposed_change, service=service)
174
192
 
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
193
 
194
+ @task(name="Cancel a propose change", description="Cancel a propose change", cache_policy=NONE) # type: ignore[arg-type]
195
+ async def cancel_proposed_change(proposed_change: CoreProposedChange, service: InfrahubServices) -> None:
179
196
  await add_tags(nodes=[proposed_change.id])
180
197
  log = get_run_logger()
181
198
 
@@ -189,11 +206,12 @@ async def cancel_proposed_change(proposed_change: CoreProposedChange) -> None:
189
206
  name="proposed-changed-data-integrity",
190
207
  flow_run_name="Triggers data integrity check",
191
208
  )
192
- async def run_proposed_change_data_integrity_check(model: RequestProposedChangeDataIntegrity) -> None:
209
+ async def run_proposed_change_data_integrity_check(
210
+ model: RequestProposedChangeDataIntegrity, service: InfrahubServices
211
+ ) -> None:
193
212
  """Triggers a data integrity validation check on the provided proposed change to start."""
194
213
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
195
214
 
196
- service = services.service
197
215
  async with service.database.start_transaction() as dbt:
198
216
  destination_branch = await registry.get_branch(db=dbt, branch=model.destination_branch)
199
217
  source_branch = await registry.get_branch(db=dbt, branch=model.source_branch)
@@ -207,8 +225,9 @@ async def run_proposed_change_data_integrity_check(model: RequestProposedChangeD
207
225
  name="proposed-changed-run-generator",
208
226
  flow_run_name="Run generators",
209
227
  )
210
- async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
211
- service = services.service
228
+ async def run_generators(
229
+ model: RequestProposedChangeRunGenerators, context: InfrahubContext, service: InfrahubServices
230
+ ) -> None:
212
231
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change], db_change=True)
213
232
 
214
233
  generators = await service.client.filters(
@@ -264,12 +283,13 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
264
283
  destination_branch=model.destination_branch,
265
284
  )
266
285
  msg.assign_meta(parent=model)
267
- await service.send(message=msg)
286
+ await service.message_bus.send(message=msg)
268
287
 
269
288
  next_messages: list[InfrahubMessage] = []
270
289
  if model.refresh_artifacts:
271
290
  next_messages.append(
272
291
  messages.RequestProposedChangeRefreshArtifacts(
292
+ context=context,
273
293
  proposed_change=model.proposed_change,
274
294
  source_branch=model.source_branch,
275
295
  source_branch_sync_with_git=model.source_branch_sync_with_git,
@@ -287,12 +307,14 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
287
307
  branch_diff=model.branch_diff,
288
308
  )
289
309
  await service.workflow.submit_workflow(
290
- workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS, parameters={"model": model_proposed_change_repo_checks}
310
+ workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
311
+ context=context,
312
+ parameters={"model": model_proposed_change_repo_checks},
291
313
  )
292
314
 
293
315
  for next_msg in next_messages:
294
316
  next_msg.assign_meta(parent=model)
295
- await service.send(message=next_msg)
317
+ await service.message_bus.send(message=next_msg)
296
318
 
297
319
 
298
320
  @flow(
@@ -300,11 +322,10 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
300
322
  flow_run_name="Process schema integrity",
301
323
  )
302
324
  async def run_proposed_change_schema_integrity_check(
303
- model: RequestProposedChangeSchemaIntegrity,
325
+ model: RequestProposedChangeSchemaIntegrity, service: InfrahubServices
304
326
  ) -> None:
305
327
  # For now, we retrieve the latest schema for each branch from the registry
306
328
  # In the future it would be good to generate the object SchemaUpdateValidationResult from message.branch_diff
307
- service = services.service
308
329
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
309
330
 
310
331
  source_schema = registry.schema.get_schema_branch(name=model.source_branch).duplicate()
@@ -331,7 +352,8 @@ async def run_proposed_change_schema_integrity_check(
331
352
  responses = await schema_validate_migrations(
332
353
  message=SchemaValidateMigrationData(
333
354
  branch=source_branch, schema_branch=candidate_schema, constraints=list(constraints)
334
- )
355
+ ),
356
+ service=service,
335
357
  )
336
358
 
337
359
  # TODO we need to report a failure if an error happened during the execution of a validator
@@ -393,48 +415,44 @@ async def _get_proposed_change_schema_integrity_constraints(
393
415
  name="proposed-changed-repository-checks",
394
416
  flow_run_name="Process user defined checks",
395
417
  )
396
- async def repository_checks(model: RequestProposedChangeRepositoryChecks) -> None:
397
- service = services.service
418
+ async def repository_checks(model: RequestProposedChangeRepositoryChecks, service: InfrahubServices) -> None:
398
419
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
399
420
 
400
- events: list[InfrahubMessage] = []
401
421
  for repository in model.branch_diff.repositories:
402
422
  if (
403
423
  model.source_branch_sync_with_git
404
424
  and not repository.read_only
405
425
  and repository.internal_status == RepositoryInternalStatus.ACTIVE.value
406
426
  ):
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(
427
+ trigger_internal_checks_model = TriggerRepositoryInternalChecks(
418
428
  proposed_change=model.proposed_change,
419
- repository_id=repository.repository_id,
420
- repository_name=repository.repository_name,
429
+ repository=repository.repository_id,
421
430
  source_branch=model.source_branch,
422
- source_branch_sync_with_git=model.source_branch_sync_with_git,
423
431
  target_branch=model.destination_branch,
424
- branch_diff=model.branch_diff,
425
432
  )
433
+ await service.workflow.submit_workflow(
434
+ workflow=GIT_REPOSITORY_INTERNAL_CHECKS_TRIGGER, parameters={"model": trigger_internal_checks_model}
435
+ )
436
+
437
+ trigger_user_checks_model = TriggerRepositoryUserChecks(
438
+ proposed_change=model.proposed_change,
439
+ repository_id=repository.repository_id,
440
+ repository_name=repository.repository_name,
441
+ source_branch=model.source_branch,
442
+ source_branch_sync_with_git=model.source_branch_sync_with_git,
443
+ target_branch=model.destination_branch,
444
+ branch_diff=model.branch_diff,
445
+ )
446
+ await service.workflow.submit_workflow(
447
+ workflow=GIT_REPOSITORY_USER_CHECKS_TRIGGER, parameters={"model": trigger_user_checks_model}
426
448
  )
427
- for event in events:
428
- event.assign_meta(parent=model)
429
- await service.send(message=event)
430
449
 
431
450
 
432
451
  @flow(
433
452
  name="proposed-changed-user-tests",
434
453
  flow_run_name="Run unit tests in repositories",
435
454
  )
436
- async def run_proposed_change_user_tests(model: RequestProposedChangeUserTests) -> None:
437
- service = services.service
455
+ async def run_proposed_change_user_tests(model: RequestProposedChangeUserTests, service: InfrahubServices) -> None:
438
456
  log = get_run_logger()
439
457
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
440
458
  proposed_change = await service.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=model.proposed_change)
@@ -493,3 +511,127 @@ async def run_proposed_change_user_tests(model: RequestProposedChangeUserTests)
493
511
 
494
512
  return_code = await asyncio.to_thread(_execute, worktree_directory, repository, proposed_change)
495
513
  log.info(msg=f"repository_tests_completed return_code={return_code}")
514
+
515
+
516
+ @flow(
517
+ name="artifacts-generation-validation",
518
+ flow_run_name="Validating generation of artifacts for {model.artifact_definition.definition_name}",
519
+ )
520
+ async def validate_artifacts_generation(model: RequestArtifactDefinitionCheck, service: InfrahubServices) -> None:
521
+ await add_tags(branches=[model.source_branch], nodes=[model.proposed_change], db_change=True)
522
+
523
+ log = get_run_logger()
524
+ artifact_definition = await service.client.get(
525
+ kind=InfrahubKind.ARTIFACTDEFINITION,
526
+ id=model.artifact_definition.definition_id,
527
+ branch=model.source_branch,
528
+ )
529
+ proposed_change = await service.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=model.proposed_change)
530
+
531
+ validator_name = f"Artifact Validator: {model.artifact_definition.definition_name}"
532
+
533
+ await proposed_change.validations.fetch()
534
+
535
+ validator = None
536
+ for relationship in proposed_change.validations.peers:
537
+ existing_validator = relationship.peer
538
+ if (
539
+ existing_validator.typename == InfrahubKind.ARTIFACTVALIDATOR
540
+ and existing_validator.definition.id == model.artifact_definition.definition_id
541
+ ):
542
+ validator = existing_validator
543
+
544
+ if validator:
545
+ validator.conclusion.value = ValidatorConclusion.UNKNOWN.value
546
+ validator.state.value = ValidatorState.QUEUED.value
547
+ validator.started_at.value = ""
548
+ validator.completed_at.value = ""
549
+ await validator.save()
550
+ else:
551
+ validator = await service.client.create(
552
+ kind=InfrahubKind.ARTIFACTVALIDATOR,
553
+ data={
554
+ "label": validator_name,
555
+ "proposed_change": model.proposed_change,
556
+ "definition": model.artifact_definition.definition_id,
557
+ },
558
+ )
559
+ await validator.save()
560
+
561
+ await artifact_definition.targets.fetch()
562
+ group = artifact_definition.targets.peer
563
+ await group.members.fetch()
564
+
565
+ existing_artifacts = await service.client.filters(
566
+ kind=InfrahubKind.ARTIFACT,
567
+ definition__ids=[model.artifact_definition.definition_id],
568
+ include=["object"],
569
+ branch=model.source_branch,
570
+ )
571
+ artifacts_by_member = {}
572
+ for artifact in existing_artifacts:
573
+ artifacts_by_member[artifact.object.peer.id] = artifact.id
574
+
575
+ repository = model.branch_diff.get_repository(repository_id=model.artifact_definition.repository_id)
576
+ impacted_artifacts = model.branch_diff.get_subscribers_ids(kind=InfrahubKind.ARTIFACT)
577
+
578
+ checks = []
579
+
580
+ for relationship in group.members.peers:
581
+ member = relationship.peer
582
+ artifact_id = artifacts_by_member.get(member.id)
583
+ if _should_render_artifact(
584
+ artifact_id=artifact_id,
585
+ managed_branch=model.source_branch_sync_with_git,
586
+ impacted_artifacts=impacted_artifacts,
587
+ ):
588
+ log.info(f"Trigger Artifact processing for {member.display_label}")
589
+
590
+ check_model = CheckArtifactCreate(
591
+ context=model.context,
592
+ artifact_name=model.artifact_definition.artifact_name,
593
+ artifact_id=artifact_id,
594
+ artifact_definition=model.artifact_definition.definition_id,
595
+ commit=repository.source_commit,
596
+ content_type=model.artifact_definition.content_type,
597
+ transform_type=model.artifact_definition.transform_kind,
598
+ transform_location=model.artifact_definition.transform_location,
599
+ repository_id=repository.repository_id,
600
+ repository_name=repository.repository_name,
601
+ repository_kind=repository.kind,
602
+ branch_name=model.source_branch,
603
+ query=model.artifact_definition.query_name,
604
+ variables=member.extract(params=artifact_definition.parameters.value),
605
+ target_id=member.id,
606
+ target_kind=member.get_kind(),
607
+ target_name=member.display_label,
608
+ timeout=model.artifact_definition.timeout,
609
+ validator_id=validator.id,
610
+ )
611
+
612
+ checks.append(
613
+ service.workflow.execute_workflow(
614
+ workflow=GIT_REPOSITORIES_CHECK_ARTIFACT_CREATE,
615
+ parameters={"model": check_model},
616
+ expected_return=ValidatorConclusion,
617
+ )
618
+ )
619
+
620
+ await run_checks_and_update_validator(checks, validator)
621
+
622
+
623
+ def _should_render_artifact(artifact_id: str | None, managed_branch: bool, impacted_artifacts: list[str]) -> bool: # noqa: ARG001
624
+ """Returns a boolean to indicate if an artifact should be generated or not.
625
+ Will return true if:
626
+ * The artifact_id wasn't set which could be that it's a new object that doesn't have a previous artifact
627
+ * The source brance is not data only which would indicate that it could contain updates in git to the transform
628
+ * The artifact_id exists in the impacted_artifacts list
629
+ Will return false if:
630
+ * The source branch is a data only branch and the artifact_id exists and is not in the impacted list
631
+ """
632
+
633
+ # if not artifact_id or managed_branch:
634
+ # return True
635
+ # return artifact_id in impacted_artifacts
636
+ # Temporary workaround tracked in https://github.com/opsmill/infrahub/issues/4991
637
+ return True
infrahub/pytest_plugin.py CHANGED
@@ -52,7 +52,7 @@ class InfrahubBackendPlugin:
52
52
 
53
53
  return validator, True
54
54
 
55
- def pytest_collection_modifyitems(self, session: Session, config: Config, items: list[Item]) -> None: # pylint: disable=unused-argument
55
+ def pytest_collection_modifyitems(self, session: Session, config: Config, items: list[Item]) -> None: # noqa: ARG002
56
56
  """This function is called after item collection and gives the opportunity to work on the collection before sending the items for testing.
57
57
 
58
58
  All items without an "infrahub" marker will be discarded. Items will also be re-ordered to be run in a specific order:
@@ -82,7 +82,7 @@ class InfrahubBackendPlugin:
82
82
  filtered_items.sort(key=sort_key)
83
83
  items[:] = filtered_items
84
84
 
85
- def pytest_collection_finish(self, session: Session) -> None: # pylint: disable=unused-argument
85
+ def pytest_collection_finish(self, session: Session) -> None: # noqa: ARG002
86
86
  """This function is called when tests have been collected and modified, meaning they are ready to be run."""
87
87
  self.proposed_change = self.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=self.proposed_change_id)
88
88
  self.proposed_change.validations.fetch()
@@ -95,7 +95,7 @@ class InfrahubBackendPlugin:
95
95
  check = relationship.peer
96
96
  self.checks[check.origin.value] = check
97
97
 
98
- def pytest_runtestloop(self, session: Session) -> Optional[object]: # pylint: disable=unused-argument,useless-return
98
+ def pytest_runtestloop(self, session: Session) -> Optional[object]: # noqa: ARG002
99
99
  """This function is called when the test loop is being run."""
100
100
  self.validator.conclusion.value = "unknown"
101
101
  self.validator.state.value = "in_progress"
@@ -144,7 +144,7 @@ class InfrahubBackendPlugin:
144
144
  # Workaround for https://github.com/opsmill/infrahub/issues/2184
145
145
  check.update(do_full_update=True)
146
146
 
147
- def pytest_sessionfinish(self, session: Session) -> None: # pylint: disable=unused-argument
147
+ def pytest_sessionfinish(self, session: Session) -> None: # noqa: ARG002
148
148
  """Set the final RepositoryValidator details after completing the test session."""
149
149
  conclusion = "success"
150
150
 
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})