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
infrahub/git/tasks.py CHANGED
@@ -1,31 +1,34 @@
1
- from datetime import timedelta
2
-
3
1
  from infrahub_sdk import InfrahubClient
4
- from infrahub_sdk.protocols import CoreArtifact, CoreArtifactDefinition, CoreRepository
2
+ from infrahub_sdk.protocols import CoreArtifact, CoreArtifactDefinition, CoreCheckDefinition, CoreRepository
3
+ from infrahub_sdk.uuidt import UUIDT
5
4
  from prefect import flow, task
6
- from prefect.automations import AutomationCore
7
5
  from prefect.cache_policies import NONE
8
- from prefect.client.orchestration import get_client
9
- from prefect.client.schemas.filters import DeploymentFilter, DeploymentFilterName
10
- from prefect.events.actions import RunDeployment
11
- from prefect.events.schemas.automations import EventTrigger, Posture
12
6
  from prefect.logging import get_run_logger
13
7
 
14
8
  from infrahub import lock
15
- from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus
9
+ from infrahub.context import InfrahubContext
10
+ from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus, ValidatorConclusion, ValidatorState
16
11
  from infrahub.core.registry import registry
17
- from infrahub.exceptions import RepositoryError
12
+ from infrahub.exceptions import CheckError, RepositoryError
18
13
  from infrahub.message_bus import Meta, messages
19
- from infrahub.services import services
14
+ from infrahub.services import InfrahubServices
20
15
  from infrahub.worker import WORKER_IDENTITY
21
- from infrahub.workflows.catalogue import COMPUTED_ATTRIBUTE_SETUP_PYTHON
22
16
 
17
+ from ..core.manager import NodeManager
18
+ from ..core.timestamp import Timestamp
19
+ from ..core.validators.checks_runner import run_checks_and_update_validator
23
20
  from ..log import get_log_data
24
21
  from ..tasks.artifact import define_artifact
25
- from ..workflows.catalogue import REQUEST_ARTIFACT_DEFINITION_GENERATE, REQUEST_ARTIFACT_GENERATE
22
+ from ..workflows.catalogue import (
23
+ GIT_REPOSITORY_MERGE_CONFLICTS_CHECKS_RUN,
24
+ GIT_REPOSITORY_USER_CHECK_RUN,
25
+ GIT_REPOSITORY_USER_CHECKS_DEFINITIONS_TRIGGER,
26
+ REQUEST_ARTIFACT_DEFINITION_GENERATE,
27
+ REQUEST_ARTIFACT_GENERATE,
28
+ )
26
29
  from ..workflows.utils import add_branch_tag, add_tags
27
- from .constants import AUTOMATION_NAME
28
30
  from .models import (
31
+ CheckRepositoryMergeConflicts,
29
32
  GitDiffNamesOnly,
30
33
  GitDiffNamesOnlyResponse,
31
34
  GitRepositoryAdd,
@@ -35,6 +38,10 @@ from .models import (
35
38
  GitRepositoryPullReadOnly,
36
39
  RequestArtifactDefinitionGenerate,
37
40
  RequestArtifactGenerate,
41
+ TriggerRepositoryInternalChecks,
42
+ TriggerRepositoryUserChecks,
43
+ UserCheckData,
44
+ UserCheckDefinitionData,
38
45
  )
39
46
  from .repository import InfrahubReadOnlyRepository, InfrahubRepository, get_initialized_repo
40
47
 
@@ -43,8 +50,7 @@ from .repository import InfrahubReadOnlyRepository, InfrahubRepository, get_init
43
50
  name="git-repository-add-read-write",
44
51
  flow_run_name="Adding repository {model.repository_name} in branch {model.infrahub_branch_name}",
45
52
  )
46
- async def add_git_repository(model: GitRepositoryAdd) -> None:
47
- service = services.service
53
+ async def add_git_repository(model: GitRepositoryAdd, service: InfrahubServices) -> None:
48
54
  await add_tags(branches=[model.infrahub_branch_name], nodes=[model.repository_id])
49
55
 
50
56
  async with lock.registry.get(name=model.repository_name, namespace="repository"):
@@ -56,8 +62,9 @@ async def add_git_repository(model: GitRepositoryAdd) -> None:
56
62
  infrahub_branch_name=model.infrahub_branch_name,
57
63
  internal_status=model.internal_status,
58
64
  default_branch_name=model.default_branch_name,
65
+ service=service,
59
66
  )
60
- await repo.import_objects_from_files(
67
+ await repo.import_objects_from_files( # type: ignore[call-overload]
61
68
  infrahub_branch_name=model.infrahub_branch_name, git_branch_name=model.default_branch_name
62
69
  )
63
70
  if model.internal_status == RepositoryInternalStatus.ACTIVE.value:
@@ -73,15 +80,14 @@ async def add_git_repository(model: GitRepositoryAdd) -> None:
73
80
  infrahub_branch_name=model.infrahub_branch_name,
74
81
  infrahub_branch_id=model.infrahub_branch_id,
75
82
  )
76
- await service.send(message=notification)
83
+ await service.message_bus.send(message=notification)
77
84
 
78
85
 
79
86
  @flow(
80
87
  name="git-repository-add-read-only",
81
88
  flow_run_name="Adding read only repository {model.repository_name} in branch {model.infrahub_branch_name}",
82
89
  )
83
- async def add_git_repository_read_only(model: GitRepositoryAddReadOnly) -> None:
84
- service = services.service
90
+ async def add_git_repository_read_only(model: GitRepositoryAddReadOnly, service: InfrahubServices) -> None:
85
91
  await add_tags(branches=[model.infrahub_branch_name], nodes=[model.repository_id])
86
92
 
87
93
  async with lock.registry.get(name=model.repository_name, namespace="repository"):
@@ -92,8 +98,9 @@ async def add_git_repository_read_only(model: GitRepositoryAddReadOnly) -> None:
92
98
  client=service.client,
93
99
  ref=model.ref,
94
100
  infrahub_branch_name=model.infrahub_branch_name,
101
+ service=service,
95
102
  )
96
- await repo.import_objects_from_files(infrahub_branch_name=model.infrahub_branch_name)
103
+ await repo.import_objects_from_files(infrahub_branch_name=model.infrahub_branch_name) # type: ignore[call-overload]
97
104
  if model.internal_status == RepositoryInternalStatus.ACTIVE.value:
98
105
  await repo.sync_from_remote()
99
106
 
@@ -107,13 +114,12 @@ async def add_git_repository_read_only(model: GitRepositoryAddReadOnly) -> None:
107
114
  infrahub_branch_name=model.infrahub_branch_name,
108
115
  infrahub_branch_id=model.infrahub_branch_id,
109
116
  )
110
- await service.send(message=notification)
117
+ await service.message_bus.send(message=notification)
111
118
 
112
119
 
113
120
  @flow(name="git-repositories-create-branch", flow_run_name="Create branch '{branch}' in Git Repositories")
114
- async def create_branch(branch: str, branch_id: str) -> None:
121
+ async def create_branch(branch: str, branch_id: str, service: InfrahubServices) -> None:
115
122
  """Request to the creation of git branches in available repositories."""
116
- service = services.service
117
123
  await add_tags(branches=[branch])
118
124
  repositories: list[CoreRepository] = await service.client.filters(kind=CoreRepository)
119
125
  batch = await service.client.create_batch()
@@ -126,6 +132,7 @@ async def create_branch(branch: str, branch_id: str) -> None:
126
132
  repository_name=repository.name.value,
127
133
  repository_id=repository.id,
128
134
  repository_location=repository.location.value,
135
+ service=service,
129
136
  )
130
137
 
131
138
  async for _, _ in batch.execute():
@@ -133,9 +140,7 @@ async def create_branch(branch: str, branch_id: str) -> None:
133
140
 
134
141
 
135
142
  @flow(name="git_repositories_sync", flow_run_name="Sync Git Repositories")
136
- async def sync_remote_repositories() -> None:
137
- service = services.service
138
-
143
+ async def sync_remote_repositories(service: InfrahubServices) -> None:
139
144
  log = get_run_logger()
140
145
 
141
146
  branches = await service.client.branch.all()
@@ -178,7 +183,7 @@ async def sync_remote_repositories() -> None:
178
183
  internal_status=active_internal_status,
179
184
  default_branch_name=repository_data.repository.default_branch.value,
180
185
  )
181
- await repo.import_objects_from_files(
186
+ await repo.import_objects_from_files( # type: ignore[call-overload]
182
187
  git_branch_name=registry.default_branch, infrahub_branch_name=infrahub_branch
183
188
  )
184
189
  except RepositoryError as exc:
@@ -197,12 +202,12 @@ async def sync_remote_repositories() -> None:
197
202
  infrahub_branch_name=infrahub_branch,
198
203
  infrahub_branch_id=branches[infrahub_branch].id,
199
204
  )
200
- await service.send(message=message)
205
+ await service.message_bus.send(message=message)
201
206
  except RepositoryError as exc:
202
207
  log.info(exc.message)
203
208
 
204
209
 
205
- @task(
210
+ @task( # type: ignore[arg-type]
206
211
  name="git-branch-create",
207
212
  task_run_name="Create branch '{branch}' in repository {repository_name}",
208
213
  cache_policy=NONE,
@@ -214,11 +219,11 @@ async def git_branch_create(
214
219
  repository_id: str,
215
220
  repository_name: str,
216
221
  repository_location: str,
222
+ service: InfrahubServices,
217
223
  ) -> None:
218
- service = services.service
219
224
  log = get_run_logger()
220
225
  repo = await InfrahubRepository.init(
221
- id=repository_id, name=repository_name, location=repository_location, client=client
226
+ id=repository_id, name=repository_name, location=repository_location, client=client, service=service
222
227
  )
223
228
 
224
229
  async with lock.registry.get(name=repository_name, namespace="repository"):
@@ -234,13 +239,12 @@ async def git_branch_create(
234
239
  infrahub_branch_name=branch,
235
240
  infrahub_branch_id=branch_id,
236
241
  )
237
- await service.send(message=message)
242
+ await service.message_bus.send(message=message)
238
243
  log.debug("Sent message to all workers to fetch the latest version of the repository (RefreshGitFetch)")
239
244
 
240
245
 
241
246
  @flow(name="artifact-definition-generate", flow_run_name="Generate all artifacts")
242
- async def generate_artifact_definition(branch: str) -> None:
243
- service = services.service
247
+ async def generate_artifact_definition(branch: str, context: InfrahubContext, service: InfrahubServices) -> None:
244
248
  await add_branch_tag(branch_name=branch)
245
249
 
246
250
  artifact_definitions = await service.client.all(kind=CoreArtifactDefinition, branch=branch, include=["id"])
@@ -252,14 +256,12 @@ async def generate_artifact_definition(branch: str) -> None:
252
256
  artifact_definition_name=artifact_definition.name.value,
253
257
  )
254
258
  await service.workflow.submit_workflow(
255
- workflow=REQUEST_ARTIFACT_DEFINITION_GENERATE, parameters={"model": model}
259
+ workflow=REQUEST_ARTIFACT_DEFINITION_GENERATE, context=context, parameters={"model": model}
256
260
  )
257
261
 
258
262
 
259
263
  @flow(name="artifact-generate", flow_run_name="Generate artifact {model.artifact_name}")
260
- async def generate_artifact(model: RequestArtifactGenerate) -> None:
261
- service = services.service
262
-
264
+ async def generate_artifact(model: RequestArtifactGenerate, service: InfrahubServices) -> None:
263
265
  await add_tags(branches=[model.branch_name], nodes=[model.target_id])
264
266
  log = get_run_logger()
265
267
  repo = await get_initialized_repo(
@@ -270,14 +272,14 @@ async def generate_artifact(model: RequestArtifactGenerate) -> None:
270
272
  commit=model.commit,
271
273
  )
272
274
 
273
- artifact = await define_artifact(message=model, service=service)
275
+ artifact, artifact_created = await define_artifact(model=model, service=service)
274
276
 
275
277
  try:
276
- result = await repo.render_artifact(artifact=artifact, message=model)
278
+ result = await repo.render_artifact(artifact=artifact, artifact_created=artifact_created, message=model)
277
279
  log.debug(
278
280
  f"Generated artifact | changed: {result.changed} | {result.checksum} | {result.storage_id}",
279
281
  )
280
- except Exception: # pylint: disable=broad-except
282
+ except Exception:
281
283
  log.exception("Failed to generate artifact")
282
284
  artifact.status.value = "Error"
283
285
  await artifact.save()
@@ -288,9 +290,10 @@ async def generate_artifact(model: RequestArtifactGenerate) -> None:
288
290
  name="request_artifact_definitions_generate",
289
291
  flow_run_name="Trigger Generation of Artifacts for {model.artifact_definition_name}",
290
292
  )
291
- async def generate_request_artifact_definition(model: RequestArtifactDefinitionGenerate) -> None:
292
- service = services.service
293
- await add_tags(branches=[model.branch], nodes=[model.artifact_definition_id])
293
+ async def generate_request_artifact_definition(
294
+ model: RequestArtifactDefinitionGenerate, context: InfrahubContext, service: InfrahubServices
295
+ ) -> None:
296
+ await add_tags(branches=[model.branch])
294
297
 
295
298
  artifact_definition = await service.client.get(
296
299
  kind=CoreArtifactDefinition, id=model.artifact_definition_id, branch=model.branch
@@ -355,18 +358,18 @@ async def generate_request_artifact_definition(model: RequestArtifactDefinitionG
355
358
  variables=member.extract(params=artifact_definition.parameters.value),
356
359
  target_id=member.id,
357
360
  target_name=member.display_label,
361
+ target_kind=member.get_kind(),
358
362
  timeout=transform.timeout.value,
363
+ context=context,
359
364
  )
360
365
 
361
366
  await service.workflow.submit_workflow(
362
- workflow=REQUEST_ARTIFACT_GENERATE, parameters={"model": request_artifact_generate_model}
367
+ workflow=REQUEST_ARTIFACT_GENERATE, context=context, parameters={"model": request_artifact_generate_model}
363
368
  )
364
369
 
365
370
 
366
371
  @flow(name="git-repository-pull-read-only", flow_run_name="Pull latest commit on {model.repository_name}")
367
- async def pull_read_only(model: GitRepositoryPullReadOnly) -> None:
368
- service = services.service
369
-
372
+ async def pull_read_only(model: GitRepositoryPullReadOnly, service: InfrahubServices) -> None:
370
373
  await add_tags(branches=[model.infrahub_branch_name], nodes=[model.repository_id])
371
374
  log = get_run_logger()
372
375
 
@@ -383,6 +386,7 @@ async def pull_read_only(model: GitRepositoryPullReadOnly) -> None:
383
386
  client=service.client,
384
387
  ref=model.ref,
385
388
  infrahub_branch_name=model.infrahub_branch_name,
389
+ service=service,
386
390
  )
387
391
  except RepositoryError:
388
392
  init_failed = True
@@ -395,9 +399,10 @@ async def pull_read_only(model: GitRepositoryPullReadOnly) -> None:
395
399
  client=service.client,
396
400
  ref=model.ref,
397
401
  infrahub_branch_name=model.infrahub_branch_name,
402
+ service=service,
398
403
  )
399
404
 
400
- await repo.import_objects_from_files(infrahub_branch_name=model.infrahub_branch_name, commit=model.commit)
405
+ await repo.import_objects_from_files(infrahub_branch_name=model.infrahub_branch_name, commit=model.commit) # type: ignore[call-overload]
401
406
  await repo.sync_from_remote(commit=model.commit)
402
407
 
403
408
  # Tell workers to fetch to stay in sync
@@ -410,16 +415,14 @@ async def pull_read_only(model: GitRepositoryPullReadOnly) -> None:
410
415
  infrahub_branch_name=model.infrahub_branch_name,
411
416
  infrahub_branch_id=model.infrahub_branch_id,
412
417
  )
413
- await service.send(message=message)
418
+ await service.message_bus.send(message=message)
414
419
 
415
420
 
416
421
  @flow(
417
422
  name="git-repository-merge",
418
423
  flow_run_name="Merge {model.source_branch} > {model.destination_branch} in git repository",
419
424
  )
420
- async def merge_git_repository(model: GitRepositoryMerge) -> None:
421
- service = services.service
422
-
425
+ async def merge_git_repository(model: GitRepositoryMerge, service: InfrahubServices) -> None:
423
426
  await add_tags(branches=[model.source_branch, model.destination_branch], nodes=[model.repository_id])
424
427
 
425
428
  repo = await InfrahubRepository.init(
@@ -427,6 +430,7 @@ async def merge_git_repository(model: GitRepositoryMerge) -> None:
427
430
  name=model.repository_name,
428
431
  client=service.client,
429
432
  default_branch_name=model.default_branch,
433
+ service=service,
430
434
  )
431
435
 
432
436
  if model.internal_status == RepositoryInternalStatus.STAGING.value:
@@ -455,71 +459,20 @@ async def merge_git_repository(model: GitRepositoryMerge) -> None:
455
459
  infrahub_branch_name=model.destination_branch,
456
460
  infrahub_branch_id=model.destination_branch_id,
457
461
  )
458
- await service.send(message=message)
459
-
460
-
461
- @flow(name="git-commit-automation-setup", flow_run_name="Setup git commit updated event in task-manager")
462
- async def setup_commit_automation() -> None:
463
- log = get_run_logger()
464
-
465
- async with get_client(sync_client=False) as client:
466
- deployments = {
467
- item.name: item
468
- for item in await client.read_deployments(
469
- deployment_filter=DeploymentFilter(
470
- name=DeploymentFilterName(any_=[COMPUTED_ATTRIBUTE_SETUP_PYTHON.name])
471
- )
472
- )
473
- }
474
- if COMPUTED_ATTRIBUTE_SETUP_PYTHON.name not in deployments:
475
- raise ValueError("Unable to find the deployment for COMPUTED_ATTRIBUTE_SETUP_PYTHON")
476
-
477
- deployment_id_computed_attribute_setup_python = deployments[COMPUTED_ATTRIBUTE_SETUP_PYTHON.name].id
478
-
479
- schema_update_automation = await client.find_automation(id_or_name=AUTOMATION_NAME)
480
-
481
- automation = AutomationCore(
482
- name=AUTOMATION_NAME,
483
- description="Trigger actions on schema update event",
484
- enabled=True,
485
- trigger=EventTrigger(
486
- posture=Posture.Reactive,
487
- expect={"infrahub.repository.update_commit"},
488
- within=timedelta(0),
489
- threshold=1,
490
- ),
491
- actions=[
492
- RunDeployment(
493
- source="selected",
494
- deployment_id=deployment_id_computed_attribute_setup_python,
495
- parameters={
496
- "branch_name": "{{ event.resource['infrahub.branch.name'] }}",
497
- "commit": "{{ event.payload['commit'] }}",
498
- },
499
- job_variables={},
500
- ),
501
- ],
502
- )
503
-
504
- if schema_update_automation:
505
- await client.update_automation(automation_id=schema_update_automation.id, automation=automation)
506
- log.info(f"{AUTOMATION_NAME} Updated")
507
- else:
508
- await client.create_automation(automation=automation)
509
- log.info(f"{AUTOMATION_NAME} Created")
462
+ await service.message_bus.send(message=message)
510
463
 
511
464
 
512
465
  @flow(name="git-repository-import-object", flow_run_name="Import objects from git repository")
513
- async def import_objects_from_git_repository(model: GitRepositoryImportObjects) -> None:
466
+ async def import_objects_from_git_repository(model: GitRepositoryImportObjects, service: InfrahubServices) -> None:
514
467
  await add_branch_tag(model.infrahub_branch_name)
515
468
  repo = await get_initialized_repo(
516
469
  repository_id=model.repository_id,
517
470
  name=model.repository_name,
518
- service=services.service,
471
+ service=service,
519
472
  repository_kind=model.repository_kind,
520
473
  commit=model.commit,
521
474
  )
522
- await repo.import_objects_from_files(infrahub_branch_name=model.infrahub_branch_name, commit=model.commit)
475
+ await repo.import_objects_from_files(infrahub_branch_name=model.infrahub_branch_name, commit=model.commit) # type: ignore[call-overload]
523
476
 
524
477
 
525
478
  @flow(
@@ -527,9 +480,9 @@ async def import_objects_from_git_repository(model: GitRepositoryImportObjects)
527
480
  flow_run_name="Collecting modifications between commits {model.first_commit} and {model.second_commit}",
528
481
  persist_result=True,
529
482
  )
530
- async def git_repository_diff_names_only(model: GitDiffNamesOnly) -> GitDiffNamesOnlyResponse:
531
- service = services.service
532
-
483
+ async def git_repository_diff_names_only(
484
+ model: GitDiffNamesOnly, service: InfrahubServices
485
+ ) -> GitDiffNamesOnlyResponse:
533
486
  repo = await get_initialized_repo(
534
487
  repository_id=model.repository_id,
535
488
  name=model.repository_name,
@@ -550,3 +503,370 @@ async def git_repository_diff_names_only(model: GitDiffNamesOnly) -> GitDiffName
550
503
  files_added=files_added, files_changed=files_changed, files_removed=files_removed
551
504
  )
552
505
  return response
506
+
507
+
508
+ @flow(
509
+ name="git-repository-user-checks-definition-trigger",
510
+ flow_run_name="Trigger user defined checks for repository {model.repository_name}",
511
+ )
512
+ async def trigger_repository_user_checks_definitions(model: UserCheckDefinitionData, service: InfrahubServices) -> None:
513
+ await add_tags(branches=[model.branch_name], nodes=[model.proposed_change])
514
+ log = get_run_logger()
515
+
516
+ definition = await service.client.get(
517
+ kind=CoreCheckDefinition, id=model.check_definition_id, branch=model.branch_name
518
+ )
519
+ proposed_change = await service.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=model.proposed_change)
520
+ validator_execution_id = str(UUIDT())
521
+ check_execution_ids: list[str] = []
522
+ await proposed_change.validations.fetch()
523
+ validator = None
524
+
525
+ for relationship in proposed_change.validations.peers:
526
+ existing_validator = relationship.peer
527
+
528
+ if (
529
+ existing_validator.typename == InfrahubKind.USERVALIDATOR
530
+ and existing_validator.repository.id == model.repository_id
531
+ and existing_validator.check_definition.id == model.check_definition_id
532
+ ):
533
+ validator = existing_validator
534
+ service.log.info("Found the same validator", validator=validator)
535
+
536
+ if validator:
537
+ validator.conclusion.value = ValidatorConclusion.UNKNOWN.value
538
+ validator.state.value = ValidatorState.QUEUED.value
539
+ validator.started_at.value = ""
540
+ validator.completed_at.value = ""
541
+ await validator.save()
542
+ else:
543
+ validator = await service.client.create(
544
+ kind=InfrahubKind.USERVALIDATOR,
545
+ data={
546
+ "label": f"Check: {definition.name.value}",
547
+ "proposed_change": model.proposed_change,
548
+ "repository": model.repository_id,
549
+ "check_definition": model.check_definition_id,
550
+ },
551
+ )
552
+ await validator.save()
553
+
554
+ if definition.targets.id:
555
+ # Check against a group of targets
556
+ await definition.targets.fetch()
557
+ group = definition.targets.peer
558
+ await group.members.fetch()
559
+ check_models = []
560
+ for relationship in group.members.peers:
561
+ member = relationship.peer
562
+
563
+ check_execution_id = str(UUIDT())
564
+ check_execution_ids.append(check_execution_id)
565
+ check_model = UserCheckData(
566
+ name=member.display_label,
567
+ validator_id=validator.id,
568
+ validator_execution_id=validator_execution_id,
569
+ check_execution_id=check_execution_id,
570
+ repository_id=model.repository_id,
571
+ repository_name=model.repository_name,
572
+ commit=model.commit,
573
+ file_path=model.file_path,
574
+ class_name=model.class_name,
575
+ branch_name=model.branch_name,
576
+ check_definition_id=model.check_definition_id,
577
+ proposed_change=model.proposed_change,
578
+ variables=member.extract(params=definition.parameters.value),
579
+ branch_diff=model.branch_diff,
580
+ timeout=definition.timeout.value,
581
+ )
582
+ check_models.append(check_model)
583
+ else:
584
+ check_execution_id = str(UUIDT())
585
+ check_execution_ids.append(check_execution_id)
586
+ check_models = [
587
+ UserCheckData(
588
+ name=definition.name.value,
589
+ validator_id=validator.id,
590
+ validator_execution_id=validator_execution_id,
591
+ check_execution_id=check_execution_id,
592
+ repository_id=model.repository_id,
593
+ repository_name=model.repository_name,
594
+ commit=model.commit,
595
+ file_path=model.file_path,
596
+ class_name=model.class_name,
597
+ branch_name=model.branch_name,
598
+ check_definition_id=model.check_definition_id,
599
+ proposed_change=model.proposed_change,
600
+ branch_diff=model.branch_diff,
601
+ timeout=definition.timeout.value,
602
+ )
603
+ ]
604
+
605
+ checks_in_execution = ",".join(check_execution_ids)
606
+ log.info(f"Checks in execution {checks_in_execution}")
607
+
608
+ checks_coroutines = [
609
+ service.workflow.execute_workflow(
610
+ workflow=GIT_REPOSITORY_USER_CHECK_RUN, parameters={"model": model}, expected_return=ValidatorConclusion
611
+ )
612
+ for model in check_models
613
+ ]
614
+
615
+ await run_checks_and_update_validator(checks_coroutines, validator)
616
+
617
+
618
+ @flow(
619
+ name="git-repository-trigger-user-checks",
620
+ flow_run_name="Evaluating user-defined checks on repository {model.repository_name}",
621
+ )
622
+ async def trigger_user_checks(model: TriggerRepositoryUserChecks, service: InfrahubServices) -> None:
623
+ """Request to start validation checks on a specific repository for User-defined checks."""
624
+
625
+ await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
626
+ log = get_run_logger()
627
+
628
+ repository = await service.client.get(
629
+ kind=InfrahubKind.GENERICREPOSITORY, id=model.repository_id, branch=model.source_branch, fragment=True
630
+ )
631
+ await repository.checks.fetch()
632
+
633
+ for relationship in repository.checks.peers:
634
+ log.info("Adding check for user defined check")
635
+ check_definition = relationship.peer
636
+ user_check_definition_model = UserCheckDefinitionData(
637
+ check_definition_id=check_definition.id,
638
+ repository_id=repository.id,
639
+ repository_name=repository.name.value,
640
+ commit=repository.commit.value,
641
+ file_path=check_definition.file_path.value,
642
+ class_name=check_definition.class_name.value,
643
+ branch_name=model.source_branch,
644
+ proposed_change=model.proposed_change,
645
+ branch_diff=model.branch_diff,
646
+ )
647
+ await service.workflow.submit_workflow(
648
+ workflow=GIT_REPOSITORY_USER_CHECKS_DEFINITIONS_TRIGGER, parameters={"model": user_check_definition_model}
649
+ )
650
+
651
+
652
+ @flow(
653
+ name="git-repository-trigger-internal-checks",
654
+ flow_run_name="Running repository checks for repository {model.repository}",
655
+ )
656
+ async def trigger_internal_checks(model: TriggerRepositoryInternalChecks, service: InfrahubServices) -> None:
657
+ """Request to start validation checks on a specific repository."""
658
+ await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
659
+ log = get_run_logger()
660
+
661
+ repository = await service.client.get(
662
+ kind=InfrahubKind.GENERICREPOSITORY, id=model.repository, branch=model.source_branch
663
+ )
664
+ proposed_change = await service.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=model.proposed_change)
665
+
666
+ validator_execution_id = str(UUIDT())
667
+ check_execution_ids: list[str] = []
668
+ await proposed_change.validations.fetch()
669
+ await repository.checks.fetch()
670
+
671
+ validator_name = f"Repository Validator: {repository.name.value}"
672
+ validator = None
673
+ for relationship in proposed_change.validations.peers:
674
+ existing_validator = relationship.peer
675
+
676
+ if (
677
+ existing_validator.typename == InfrahubKind.REPOSITORYVALIDATOR
678
+ and existing_validator.repository.id == model.repository
679
+ ):
680
+ validator = existing_validator
681
+
682
+ if validator:
683
+ validator.conclusion.value = ValidatorConclusion.UNKNOWN.value
684
+ validator.state.value = ValidatorState.QUEUED.value
685
+ validator.started_at.value = ""
686
+ validator.completed_at.value = ""
687
+ await validator.save()
688
+ else:
689
+ validator = await service.client.create(
690
+ kind=InfrahubKind.REPOSITORYVALIDATOR,
691
+ data={
692
+ "label": validator_name,
693
+ "proposed_change": model.proposed_change,
694
+ "repository": model.repository,
695
+ },
696
+ )
697
+ await validator.save()
698
+
699
+ check_execution_id = str(UUIDT())
700
+ check_execution_ids.append(check_execution_id)
701
+ log.info("Adding check for merge conflict")
702
+ checks_in_execution = ",".join(check_execution_ids)
703
+ log.info(f"Checks in execution {checks_in_execution}")
704
+
705
+ check_merge_conflict_model = CheckRepositoryMergeConflicts(
706
+ validator_id=validator.id,
707
+ validator_execution_id=validator_execution_id,
708
+ check_execution_id=check_execution_id,
709
+ proposed_change=model.proposed_change,
710
+ repository_id=model.repository,
711
+ repository_name=repository.name.value,
712
+ source_branch=model.source_branch,
713
+ target_branch=model.target_branch,
714
+ )
715
+ check_coroutine = service.workflow.execute_workflow(
716
+ workflow=GIT_REPOSITORY_MERGE_CONFLICTS_CHECKS_RUN,
717
+ parameters={"model": check_merge_conflict_model},
718
+ expected_return=ValidatorConclusion,
719
+ )
720
+
721
+ await run_checks_and_update_validator(checks=[check_coroutine], validator=validator)
722
+
723
+
724
+ @flow(
725
+ name="git-repository-check-merge-conflict",
726
+ flow_run_name="Check for merge conflicts between {model.source_branch} and {model.target_branch}",
727
+ )
728
+ async def run_check_merge_conflicts(
729
+ model: CheckRepositoryMergeConflicts, service: InfrahubServices
730
+ ) -> ValidatorConclusion:
731
+ """Runs a check to see if there are merge conflicts between two branches."""
732
+ await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
733
+
734
+ success_condition = "-"
735
+ validator = await service.client.get(kind=InfrahubKind.REPOSITORYVALIDATOR, id=model.validator_id)
736
+ await validator.checks.fetch()
737
+
738
+ repo = await InfrahubRepository.init(id=model.repository_id, name=model.repository_name, service=service)
739
+ async with lock.registry.get(name=model.repository_name, namespace="repository"):
740
+ conflicts = await repo.get_conflicts(source_branch=model.source_branch, dest_branch=model.target_branch)
741
+
742
+ existing_checks = {}
743
+ for relationship in validator.checks.peers:
744
+ existing_check = relationship.peer
745
+ if existing_check.typename == InfrahubKind.FILECHECK and existing_check.kind.value == "MergeConflictCheck":
746
+ check_key = ""
747
+ if existing_check.files.value:
748
+ check_key = "".join(existing_check.files.value)
749
+ check_key = f"-{check_key}"
750
+ existing_checks[check_key] = existing_check
751
+
752
+ if conflicts:
753
+ validator_conclusion = ValidatorConclusion.FAILURE
754
+ for conflict in conflicts:
755
+ conflict_key = f"-{conflict}"
756
+ if conflict_key in existing_checks:
757
+ existing_checks[conflict_key].created_at.value = Timestamp().to_string()
758
+ await existing_checks[conflict_key].save()
759
+ existing_checks.pop(conflict_key)
760
+ else:
761
+ check = await service.client.create(
762
+ kind=InfrahubKind.FILECHECK,
763
+ data={
764
+ "name": conflict,
765
+ "origin": "ConflictCheck",
766
+ "kind": "MergeConflictCheck",
767
+ "validator": model.validator_id,
768
+ "created_at": Timestamp().to_string(),
769
+ "files": [conflict],
770
+ "conclusion": "failure",
771
+ "severity": "critical",
772
+ },
773
+ )
774
+ await check.save()
775
+
776
+ elif success_condition in existing_checks:
777
+ validator_conclusion = ValidatorConclusion.SUCCESS
778
+ existing_checks[success_condition].created_at.value = Timestamp().to_string()
779
+ await existing_checks[success_condition].save()
780
+ existing_checks.pop(success_condition)
781
+
782
+ else:
783
+ validator_conclusion = ValidatorConclusion.SUCCESS
784
+ check = await service.client.create(
785
+ kind=InfrahubKind.FILECHECK,
786
+ data={
787
+ "name": "Merge Conflict Check",
788
+ "origin": "ConflictCheck",
789
+ "kind": "MergeConflictCheck",
790
+ "validator": model.validator_id,
791
+ "created_at": Timestamp().to_string(),
792
+ "conclusion": validator_conclusion.value,
793
+ "severity": "info",
794
+ },
795
+ )
796
+ await check.save()
797
+
798
+ async with service.database.start_session() as db:
799
+ await NodeManager.delete(db=db, nodes=list(existing_checks.values()))
800
+
801
+ return validator_conclusion
802
+
803
+
804
+ @flow(name="git-repository-run-user-check", flow_run_name="Execute user defined Check '{model.name}'")
805
+ async def run_user_check(model: UserCheckData, service: InfrahubServices) -> ValidatorConclusion:
806
+ await add_tags(branches=[model.branch_name], nodes=[model.proposed_change])
807
+ log = get_run_logger()
808
+
809
+ validator = await service.client.get(kind=InfrahubKind.USERVALIDATOR, id=model.validator_id)
810
+ await validator.checks.fetch()
811
+
812
+ repo = await InfrahubRepository.init(
813
+ id=model.repository_id, name=model.repository_name, commit=model.commit, service=service
814
+ )
815
+ conclusion = ValidatorConclusion.FAILURE
816
+ severity = "critical"
817
+ try:
818
+ check_run = await repo.execute_python_check.with_options(timeout_seconds=model.timeout)(
819
+ branch_name=model.branch_name,
820
+ location=model.file_path,
821
+ class_name=model.class_name,
822
+ client=service.client,
823
+ commit=model.commit,
824
+ params=model.variables,
825
+ )
826
+ if check_run.passed:
827
+ conclusion = ValidatorConclusion.SUCCESS
828
+ severity = "info"
829
+ log.info("The check passed")
830
+ else:
831
+ log.warning("The check reported failures")
832
+ for log_entry in check_run.log_entries:
833
+ log.warning(log_entry)
834
+ log_entries = check_run.log_entries
835
+ except CheckError as exc:
836
+ log.warning("The check failed to run")
837
+ log.error(exc.message)
838
+ log_entries = f"FATAL Error/n:{exc.message}"
839
+
840
+ check = None
841
+ for relationship in validator.checks.peers:
842
+ existing_check = relationship.peer
843
+ if (
844
+ existing_check.typename == InfrahubKind.STANDARDCHECK
845
+ and existing_check.kind.value == "CheckDefinition"
846
+ and existing_check.name.value == model.name
847
+ ):
848
+ check = existing_check
849
+
850
+ if check:
851
+ check.created_at.value = Timestamp().to_string()
852
+ check.message.value = log_entries
853
+ check.conclusion.value = conclusion.value
854
+ check.severity.value = severity
855
+ await check.save()
856
+ else:
857
+ check = await service.client.create(
858
+ kind=InfrahubKind.STANDARDCHECK,
859
+ data={
860
+ "name": model.name,
861
+ "origin": model.repository_id,
862
+ "kind": "CheckDefinition",
863
+ "validator": model.validator_id,
864
+ "created_at": Timestamp().to_string(),
865
+ "message": log_entries,
866
+ "conclusion": conclusion.value,
867
+ "severity": severity,
868
+ },
869
+ )
870
+ await check.save()
871
+
872
+ return conclusion