infrahub-server 1.1.9__py3-none-any.whl → 1.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. infrahub/api/artifact.py +16 -4
  2. infrahub/api/dependencies.py +14 -6
  3. infrahub/api/diff/validation_models.py +7 -7
  4. infrahub/api/oauth2.py +0 -1
  5. infrahub/api/oidc.py +0 -1
  6. infrahub/api/query.py +18 -7
  7. infrahub/api/schema.py +33 -7
  8. infrahub/api/transformation.py +12 -5
  9. infrahub/{message_bus/messages/check_artifact_create.py → artifacts/models.py} +6 -6
  10. infrahub/{message_bus/operations/check/artifact.py → artifacts/tasks.py} +27 -28
  11. infrahub/cli/__init__.py +12 -10
  12. infrahub/cli/constants.py +3 -0
  13. infrahub/cli/db.py +166 -185
  14. infrahub/cli/events.py +8 -3
  15. infrahub/cli/git_agent.py +9 -7
  16. infrahub/cli/tasks.py +4 -6
  17. infrahub/cli/upgrade.py +146 -0
  18. infrahub/computed_attribute/gather.py +174 -0
  19. infrahub/computed_attribute/models.py +202 -11
  20. infrahub/computed_attribute/tasks.py +103 -421
  21. infrahub/computed_attribute/triggers.py +56 -0
  22. infrahub/config.py +33 -33
  23. infrahub/context.py +53 -0
  24. infrahub/core/account.py +9 -12
  25. infrahub/core/attribute.py +104 -75
  26. infrahub/core/branch/models.py +4 -4
  27. infrahub/core/branch/tasks.py +133 -125
  28. infrahub/core/changelog/__init__.py +0 -0
  29. infrahub/core/changelog/diff.py +291 -0
  30. infrahub/core/changelog/models.py +662 -0
  31. infrahub/core/constants/__init__.py +47 -2
  32. infrahub/core/constants/infrahubkind.py +3 -0
  33. infrahub/core/constants/schema.py +2 -0
  34. infrahub/core/constraint/node/runner.py +2 -2
  35. infrahub/core/diff/branch_differ.py +10 -10
  36. infrahub/core/diff/combiner.py +1 -1
  37. infrahub/core/diff/enricher/cardinality_one.py +1 -1
  38. infrahub/core/diff/enricher/hierarchy.py +5 -3
  39. infrahub/core/diff/enricher/labels.py +1 -1
  40. infrahub/core/diff/enricher/path_identifier.py +1 -2
  41. infrahub/core/diff/enricher/summary_counts.py +107 -0
  42. infrahub/core/diff/ipam_diff_parser.py +4 -5
  43. infrahub/core/diff/merger/merger.py +3 -1
  44. infrahub/core/diff/model/diff.py +27 -27
  45. infrahub/core/diff/model/path.py +13 -13
  46. infrahub/core/diff/query/all_conflicts.py +1 -1
  47. infrahub/core/diff/query/artifact.py +1 -1
  48. infrahub/core/diff/query/delete_query.py +1 -1
  49. infrahub/core/diff/query/diff_get.py +1 -1
  50. infrahub/core/diff/query/diff_summary.py +1 -1
  51. infrahub/core/diff/query/field_specifiers.py +1 -1
  52. infrahub/core/diff/query/field_summary.py +1 -1
  53. infrahub/core/diff/query/filters.py +2 -2
  54. infrahub/core/diff/query/get_conflict_query.py +1 -1
  55. infrahub/core/diff/query/has_conflicts_query.py +1 -1
  56. infrahub/core/diff/query/merge.py +3 -3
  57. infrahub/core/diff/query/merge_tracking_id.py +1 -1
  58. infrahub/core/diff/query/roots_metadata.py +1 -1
  59. infrahub/core/diff/query/save.py +3 -3
  60. infrahub/core/diff/query/summary_counts_enricher.py +2 -2
  61. infrahub/core/diff/query/time_range_query.py +1 -1
  62. infrahub/core/diff/query/update_conflict_query.py +1 -1
  63. infrahub/core/diff/query_parser.py +4 -4
  64. infrahub/core/diff/repository/deserializer.py +1 -1
  65. infrahub/core/diff/tasks.py +9 -8
  66. infrahub/core/enums.py +1 -1
  67. infrahub/core/initialization.py +1 -10
  68. infrahub/core/integrity/object_conflict/conflict_recorder.py +1 -1
  69. infrahub/core/ipam/constants.py +3 -4
  70. infrahub/core/ipam/reconciler.py +13 -13
  71. infrahub/core/ipam/tasks.py +2 -3
  72. infrahub/core/ipam/utilization.py +10 -13
  73. infrahub/core/manager.py +52 -47
  74. infrahub/core/merge.py +12 -9
  75. infrahub/core/migrations/__init__.py +1 -3
  76. infrahub/core/migrations/graph/__init__.py +5 -3
  77. infrahub/core/migrations/graph/m001_add_version_to_graph.py +1 -1
  78. infrahub/core/migrations/graph/m002_attribute_is_default.py +2 -2
  79. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +2 -2
  80. infrahub/core/migrations/graph/m004_add_attr_documentation.py +1 -1
  81. infrahub/core/migrations/graph/m005_add_rel_read_only.py +1 -1
  82. infrahub/core/migrations/graph/m006_add_rel_on_delete.py +1 -1
  83. infrahub/core/migrations/graph/m007_add_rel_allow_override.py +1 -1
  84. infrahub/core/migrations/graph/m008_add_human_friendly_id.py +1 -1
  85. infrahub/core/migrations/graph/m009_add_generate_profile_attr.py +1 -1
  86. infrahub/core/migrations/graph/m010_add_generate_profile_attr_generic.py +1 -1
  87. infrahub/core/migrations/graph/m011_remove_profile_relationship_schema.py +2 -2
  88. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -23
  89. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -11
  90. infrahub/core/migrations/graph/m014_remove_index_attr_value.py +2 -2
  91. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
  92. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
  93. infrahub/core/migrations/graph/m017_add_core_profile.py +2 -6
  94. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +3 -3
  95. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +4 -4
  96. infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -3
  97. infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +2 -2
  98. infrahub/core/migrations/graph/m022_add_generate_template_attr.py +48 -0
  99. infrahub/core/migrations/query/attribute_add.py +3 -3
  100. infrahub/core/migrations/query/attribute_rename.py +1 -1
  101. infrahub/core/migrations/query/delete_element_in_schema.py +1 -1
  102. infrahub/core/migrations/query/node_duplicate.py +1 -1
  103. infrahub/core/migrations/query/relationship_duplicate.py +1 -1
  104. infrahub/core/migrations/query/schema_attribute_update.py +3 -3
  105. infrahub/core/migrations/schema/models.py +19 -4
  106. infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
  107. infrahub/core/migrations/schema/node_remove.py +1 -1
  108. infrahub/core/migrations/schema/tasks.py +7 -7
  109. infrahub/core/migrations/shared.py +10 -12
  110. infrahub/core/models.py +13 -14
  111. infrahub/core/node/__init__.py +172 -57
  112. infrahub/core/node/base.py +3 -5
  113. infrahub/core/node/constraints/attribute_uniqueness.py +2 -2
  114. infrahub/core/node/constraints/grouped_uniqueness.py +5 -5
  115. infrahub/core/node/constraints/interface.py +1 -2
  116. infrahub/core/node/delete_validator.py +7 -9
  117. infrahub/core/node/ipam.py +10 -10
  118. infrahub/core/node/permissions.py +7 -7
  119. infrahub/core/node/resource_manager/ip_address_pool.py +6 -6
  120. infrahub/core/node/resource_manager/ip_prefix_pool.py +14 -11
  121. infrahub/core/node/resource_manager/number_pool.py +3 -3
  122. infrahub/core/node/standard.py +3 -5
  123. infrahub/core/path.py +12 -12
  124. infrahub/core/property.py +12 -12
  125. infrahub/core/protocols.py +11 -0
  126. infrahub/core/protocols_base.py +25 -23
  127. infrahub/core/query/__init__.py +35 -38
  128. infrahub/core/query/attribute.py +13 -13
  129. infrahub/core/query/branch.py +5 -5
  130. infrahub/core/query/delete.py +1 -1
  131. infrahub/core/query/diff.py +7 -7
  132. infrahub/core/query/ipam.py +4 -4
  133. infrahub/core/query/node.py +23 -24
  134. infrahub/core/query/relationship.py +143 -46
  135. infrahub/core/query/resource_manager.py +10 -10
  136. infrahub/core/query/standard_node.py +9 -9
  137. infrahub/core/query/subquery.py +9 -9
  138. infrahub/core/query/task.py +3 -3
  139. infrahub/core/query/task_log.py +1 -1
  140. infrahub/core/query/utils.py +5 -5
  141. infrahub/core/registry.py +13 -17
  142. infrahub/core/relationship/constraints/count.py +4 -5
  143. infrahub/core/relationship/constraints/peer_kind.py +4 -5
  144. infrahub/core/relationship/constraints/profiles_kind.py +2 -2
  145. infrahub/core/relationship/model.py +103 -67
  146. infrahub/core/schema/__init__.py +6 -4
  147. infrahub/core/schema/attribute_schema.py +16 -8
  148. infrahub/core/schema/basenode_schema.py +38 -26
  149. infrahub/core/schema/computed_attribute.py +3 -3
  150. infrahub/core/schema/definitions/core/__init__.py +147 -0
  151. infrahub/core/schema/definitions/core/account.py +171 -0
  152. infrahub/core/schema/definitions/core/artifact.py +136 -0
  153. infrahub/core/schema/definitions/core/builtin.py +24 -0
  154. infrahub/core/schema/definitions/core/check.py +68 -0
  155. infrahub/core/schema/definitions/core/core.py +17 -0
  156. infrahub/core/schema/definitions/core/generator.py +100 -0
  157. infrahub/core/schema/definitions/core/graphql_query.py +79 -0
  158. infrahub/core/schema/definitions/core/group.py +108 -0
  159. infrahub/core/schema/definitions/core/ipam.py +193 -0
  160. infrahub/core/schema/definitions/core/lineage.py +19 -0
  161. infrahub/core/schema/definitions/core/menu.py +48 -0
  162. infrahub/core/schema/definitions/core/permission.py +163 -0
  163. infrahub/core/schema/definitions/core/profile.py +18 -0
  164. infrahub/core/schema/definitions/core/propose_change.py +97 -0
  165. infrahub/core/schema/definitions/core/propose_change_comment.py +193 -0
  166. infrahub/core/schema/definitions/core/propose_change_validator.py +328 -0
  167. infrahub/core/schema/definitions/core/repository.py +286 -0
  168. infrahub/core/schema/definitions/core/resource_pool.py +170 -0
  169. infrahub/core/schema/definitions/core/template.py +27 -0
  170. infrahub/core/schema/definitions/core/transform.py +96 -0
  171. infrahub/core/schema/definitions/core/webhook.py +134 -0
  172. infrahub/core/schema/definitions/internal.py +32 -16
  173. infrahub/core/schema/dropdown.py +3 -4
  174. infrahub/core/schema/generated/attribute_schema.py +15 -18
  175. infrahub/core/schema/generated/base_node_schema.py +12 -14
  176. infrahub/core/schema/generated/genericnode_schema.py +5 -0
  177. infrahub/core/schema/generated/node_schema.py +8 -5
  178. infrahub/core/schema/generated/relationship_schema.py +9 -11
  179. infrahub/core/schema/generic_schema.py +6 -2
  180. infrahub/core/schema/manager.py +46 -43
  181. infrahub/core/schema/node_schema.py +6 -2
  182. infrahub/core/schema/profile_schema.py +4 -0
  183. infrahub/core/schema/relationship_schema.py +15 -7
  184. infrahub/core/schema/schema_branch.py +423 -89
  185. infrahub/core/schema/schema_branch_computed.py +41 -4
  186. infrahub/core/schema/template_schema.py +36 -0
  187. infrahub/core/task/task.py +3 -3
  188. infrahub/core/task/user_task.py +21 -19
  189. infrahub/core/timestamp.py +3 -3
  190. infrahub/core/utils.py +12 -12
  191. infrahub/core/validators/__init__.py +1 -3
  192. infrahub/core/validators/aggregated_checker.py +2 -2
  193. infrahub/core/validators/attribute/choices.py +3 -3
  194. infrahub/core/validators/attribute/enum.py +3 -3
  195. infrahub/core/validators/attribute/kind.py +3 -3
  196. infrahub/core/validators/attribute/length.py +3 -3
  197. infrahub/core/validators/attribute/optional.py +3 -3
  198. infrahub/core/validators/attribute/regex.py +3 -3
  199. infrahub/core/validators/attribute/unique.py +3 -3
  200. infrahub/core/validators/checks_runner.py +60 -0
  201. infrahub/core/validators/determiner.py +1 -3
  202. infrahub/core/validators/model.py +1 -3
  203. infrahub/core/validators/models/validate_migration.py +17 -4
  204. infrahub/core/validators/node/attribute.py +2 -2
  205. infrahub/core/validators/node/generate_profile.py +3 -3
  206. infrahub/core/validators/node/hierarchy.py +3 -3
  207. infrahub/core/validators/node/inherit_from.py +2 -2
  208. infrahub/core/validators/node/relationship.py +2 -2
  209. infrahub/core/validators/query.py +1 -1
  210. infrahub/core/validators/relationship/count.py +5 -5
  211. infrahub/core/validators/relationship/optional.py +3 -3
  212. infrahub/core/validators/relationship/peer.py +3 -3
  213. infrahub/core/validators/shared.py +2 -2
  214. infrahub/core/validators/tasks.py +8 -6
  215. infrahub/core/validators/uniqueness/checker.py +5 -6
  216. infrahub/core/validators/uniqueness/index.py +2 -2
  217. infrahub/core/validators/uniqueness/model.py +11 -11
  218. infrahub/core/validators/uniqueness/query.py +1 -1
  219. infrahub/database/__init__.py +19 -23
  220. infrahub/database/memgraph.py +1 -1
  221. infrahub/dependencies/builder/diff/combiner.py +1 -1
  222. infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
  223. infrahub/dependencies/builder/diff/deserializer.py +1 -1
  224. infrahub/dependencies/builder/diff/enricher/summary_counts.py +8 -0
  225. infrahub/dependencies/builder/diff/parent_node_adder.py +1 -1
  226. infrahub/dependencies/component/registry.py +2 -2
  227. infrahub/events/__init__.py +25 -2
  228. infrahub/events/artifact_action.py +64 -0
  229. infrahub/events/branch_action.py +57 -20
  230. infrahub/events/generator.py +71 -0
  231. infrahub/events/group_action.py +103 -0
  232. infrahub/events/models.py +160 -53
  233. infrahub/events/node_action.py +140 -23
  234. infrahub/events/repository_action.py +7 -20
  235. infrahub/events/schema_action.py +18 -10
  236. infrahub/events/utils.py +16 -0
  237. infrahub/events/validator_action.py +55 -0
  238. infrahub/exceptions.py +12 -3
  239. infrahub/generators/models.py +2 -3
  240. infrahub/generators/tasks.py +34 -15
  241. infrahub/git/base.py +10 -12
  242. infrahub/git/constants.py +0 -1
  243. infrahub/git/integrator.py +82 -57
  244. infrahub/git/models.py +101 -9
  245. infrahub/git/repository.py +9 -10
  246. infrahub/git/tasks.py +450 -112
  247. infrahub/git/utils.py +48 -0
  248. infrahub/git/worktree.py +1 -2
  249. infrahub/git_credential/askpass.py +1 -2
  250. infrahub/git_credential/helper.py +2 -3
  251. infrahub/graphql/analyzer.py +572 -11
  252. infrahub/graphql/app.py +47 -41
  253. infrahub/graphql/auth/query_permission_checker/anonymous_checker.py +5 -5
  254. infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +4 -4
  255. infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +4 -4
  256. infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +28 -35
  257. infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -5
  258. infrahub/graphql/context.py +39 -0
  259. infrahub/graphql/enums.py +1 -1
  260. infrahub/graphql/initialization.py +5 -1
  261. infrahub/graphql/loaders/node.py +1 -1
  262. infrahub/graphql/loaders/shared.py +1 -1
  263. infrahub/graphql/manager.py +75 -72
  264. infrahub/graphql/mutations/account.py +20 -13
  265. infrahub/graphql/mutations/artifact_definition.py +18 -14
  266. infrahub/graphql/mutations/branch.py +86 -40
  267. infrahub/graphql/mutations/computed_attribute.py +26 -18
  268. infrahub/graphql/mutations/diff.py +17 -8
  269. infrahub/graphql/mutations/diff_conflict.py +14 -8
  270. infrahub/graphql/mutations/generator.py +83 -0
  271. infrahub/graphql/mutations/graphql_query.py +21 -13
  272. infrahub/graphql/mutations/ipam.py +41 -39
  273. infrahub/graphql/mutations/main.py +226 -66
  274. infrahub/graphql/mutations/menu.py +12 -12
  275. infrahub/graphql/mutations/models.py +2 -4
  276. infrahub/graphql/mutations/node_getter/by_default_filter.py +1 -3
  277. infrahub/graphql/mutations/node_getter/by_hfid.py +1 -3
  278. infrahub/graphql/mutations/node_getter/by_id.py +1 -3
  279. infrahub/graphql/mutations/node_getter/interface.py +1 -2
  280. infrahub/graphql/mutations/proposed_change.py +39 -31
  281. infrahub/graphql/mutations/relationship.py +372 -129
  282. infrahub/graphql/mutations/repository.py +46 -40
  283. infrahub/graphql/mutations/resource_manager.py +26 -26
  284. infrahub/graphql/mutations/schema.py +70 -37
  285. infrahub/graphql/mutations/tasks.py +10 -7
  286. infrahub/graphql/mutations/webhook.py +137 -0
  287. infrahub/graphql/parser.py +5 -5
  288. infrahub/graphql/permissions.py +3 -10
  289. infrahub/graphql/queries/account.py +22 -18
  290. infrahub/graphql/queries/branch.py +6 -4
  291. infrahub/graphql/queries/diff/tree.py +67 -56
  292. infrahub/graphql/queries/event.py +115 -0
  293. infrahub/graphql/queries/internal.py +3 -3
  294. infrahub/graphql/queries/ipam.py +25 -20
  295. infrahub/graphql/queries/relationship.py +13 -12
  296. infrahub/graphql/queries/resource_manager.py +37 -25
  297. infrahub/graphql/queries/search.py +11 -10
  298. infrahub/graphql/queries/status.py +12 -9
  299. infrahub/graphql/queries/task.py +11 -9
  300. infrahub/graphql/resolvers/many_relationship.py +15 -15
  301. infrahub/graphql/resolvers/resolver.py +58 -37
  302. infrahub/graphql/resolvers/single_relationship.py +16 -10
  303. infrahub/graphql/schema.py +4 -0
  304. infrahub/graphql/subscription/__init__.py +1 -1
  305. infrahub/graphql/subscription/events.py +1 -1
  306. infrahub/graphql/subscription/graphql_query.py +8 -8
  307. infrahub/graphql/types/branch.py +2 -2
  308. infrahub/graphql/types/common.py +6 -1
  309. infrahub/graphql/types/context.py +12 -0
  310. infrahub/graphql/types/enums.py +2 -0
  311. infrahub/graphql/types/event.py +167 -0
  312. infrahub/graphql/types/interface.py +2 -2
  313. infrahub/graphql/types/node.py +5 -5
  314. infrahub/graphql/types/permission.py +2 -2
  315. infrahub/graphql/types/relationship.py +3 -3
  316. infrahub/graphql/types/standard_node.py +9 -11
  317. infrahub/graphql/utils.py +30 -184
  318. infrahub/groups/ancestors.py +29 -0
  319. infrahub/groups/parsers.py +107 -0
  320. infrahub/groups/tasks.py +2 -3
  321. infrahub/lock.py +21 -21
  322. infrahub/menu/generator.py +7 -8
  323. infrahub/menu/menu.py +107 -139
  324. infrahub/menu/models.py +121 -20
  325. infrahub/menu/repository.py +111 -0
  326. infrahub/menu/utils.py +5 -8
  327. infrahub/message_bus/__init__.py +11 -13
  328. infrahub/message_bus/messages/__init__.py +1 -25
  329. infrahub/message_bus/messages/check_generator_run.py +3 -3
  330. infrahub/message_bus/messages/event_branch_merge.py +3 -0
  331. infrahub/message_bus/messages/finalize_validator_execution.py +3 -0
  332. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +6 -0
  333. infrahub/message_bus/messages/request_generatordefinition_check.py +2 -0
  334. infrahub/message_bus/messages/request_proposedchange_pipeline.py +2 -0
  335. infrahub/message_bus/messages/send_echo_request.py +1 -1
  336. infrahub/message_bus/operations/__init__.py +4 -15
  337. infrahub/message_bus/operations/check/__init__.py +2 -2
  338. infrahub/message_bus/operations/check/generator.py +2 -3
  339. infrahub/message_bus/operations/event/__init__.py +2 -2
  340. infrahub/message_bus/operations/event/branch.py +7 -3
  341. infrahub/message_bus/operations/event/worker.py +0 -3
  342. infrahub/message_bus/operations/finalize/validator.py +52 -2
  343. infrahub/message_bus/operations/git/file.py +2 -2
  344. infrahub/message_bus/operations/git/repository.py +1 -1
  345. infrahub/message_bus/operations/requests/__init__.py +0 -4
  346. infrahub/message_bus/operations/requests/generator_definition.py +22 -24
  347. infrahub/message_bus/operations/requests/proposed_change.py +39 -20
  348. infrahub/message_bus/operations/send/echo.py +1 -1
  349. infrahub/message_bus/types.py +1 -1
  350. infrahub/permissions/globals.py +15 -0
  351. infrahub/pools/number.py +2 -4
  352. infrahub/pools/prefix.py +29 -165
  353. infrahub/prefect_server/__init__.py +0 -0
  354. infrahub/prefect_server/app.py +18 -0
  355. infrahub/prefect_server/database.py +20 -0
  356. infrahub/prefect_server/events.py +28 -0
  357. infrahub/prefect_server/models.py +46 -0
  358. infrahub/proposed_change/models.py +18 -1
  359. infrahub/proposed_change/tasks.py +204 -53
  360. infrahub/pytest_plugin.py +13 -10
  361. infrahub/server.py +13 -12
  362. infrahub/services/__init__.py +148 -63
  363. infrahub/services/adapters/cache/__init__.py +11 -11
  364. infrahub/services/adapters/cache/nats.py +42 -25
  365. infrahub/services/adapters/cache/redis.py +3 -11
  366. infrahub/services/adapters/event/__init__.py +11 -19
  367. infrahub/services/adapters/http/__init__.py +0 -5
  368. infrahub/services/adapters/http/httpx.py +22 -15
  369. infrahub/services/adapters/message_bus/__init__.py +25 -8
  370. infrahub/services/adapters/message_bus/local.py +9 -7
  371. infrahub/services/adapters/message_bus/nats.py +14 -8
  372. infrahub/services/adapters/message_bus/rabbitmq.py +23 -10
  373. infrahub/services/adapters/workflow/__init__.py +11 -8
  374. infrahub/services/adapters/workflow/local.py +27 -6
  375. infrahub/services/adapters/workflow/worker.py +23 -7
  376. infrahub/services/component.py +43 -40
  377. infrahub/services/protocols.py +7 -7
  378. infrahub/services/scheduler.py +30 -29
  379. infrahub/storage.py +2 -4
  380. infrahub/task_manager/constants.py +1 -1
  381. infrahub/task_manager/event.py +275 -0
  382. infrahub/task_manager/models.py +147 -3
  383. infrahub/task_manager/task.py +1 -1
  384. infrahub/tasks/artifact.py +20 -21
  385. infrahub/tasks/registry.py +1 -1
  386. infrahub/telemetry/__init__.py +0 -0
  387. infrahub/telemetry/constants.py +9 -0
  388. infrahub/telemetry/database.py +86 -0
  389. infrahub/telemetry/models.py +65 -0
  390. infrahub/telemetry/task_manager.py +77 -0
  391. infrahub/telemetry/tasks.py +119 -0
  392. infrahub/telemetry/utils.py +11 -0
  393. infrahub/transformations/tasks.py +5 -7
  394. infrahub/trigger/__init__.py +0 -0
  395. infrahub/trigger/catalogue.py +13 -0
  396. infrahub/trigger/constants.py +1 -0
  397. infrahub/trigger/models.py +118 -0
  398. infrahub/trigger/setup.py +90 -0
  399. infrahub/trigger/tasks.py +36 -0
  400. infrahub/types.py +1 -1
  401. infrahub/utils.py +12 -2
  402. infrahub/validators/__init__.py +0 -0
  403. infrahub/validators/events.py +42 -0
  404. infrahub/validators/tasks.py +41 -0
  405. infrahub/webhook/gather.py +17 -0
  406. infrahub/webhook/models.py +180 -42
  407. infrahub/webhook/tasks.py +149 -203
  408. infrahub/webhook/triggers.py +44 -0
  409. infrahub/workers/infrahub_async.py +38 -27
  410. infrahub/workers/utils.py +63 -0
  411. infrahub/workflows/catalogue.py +98 -71
  412. infrahub/workflows/initialization.py +12 -8
  413. infrahub/workflows/models.py +29 -5
  414. infrahub/workflows/utils.py +11 -2
  415. infrahub_sdk/client.py +19 -0
  416. infrahub_sdk/context.py +13 -0
  417. infrahub_sdk/ctl/branch.py +3 -2
  418. infrahub_sdk/ctl/utils.py +0 -16
  419. infrahub_sdk/exceptions.py +6 -0
  420. infrahub_sdk/generator.py +3 -0
  421. infrahub_sdk/graphql.py +45 -13
  422. infrahub_sdk/node.py +66 -20
  423. infrahub_sdk/protocols.py +21 -8
  424. infrahub_sdk/protocols_base.py +32 -11
  425. infrahub_sdk/schema/__init__.py +14 -2
  426. infrahub_sdk/schema/main.py +7 -0
  427. infrahub_sdk/task/__init__.py +11 -0
  428. infrahub_sdk/task/constants.py +3 -0
  429. infrahub_sdk/task/exceptions.py +25 -0
  430. infrahub_sdk/task/manager.py +551 -0
  431. infrahub_sdk/task/models.py +74 -0
  432. infrahub_sdk/timestamp.py +142 -33
  433. infrahub_sdk/utils.py +29 -1
  434. {infrahub_server-1.1.9.dist-info → infrahub_server-1.2.0.dist-info}/METADATA +8 -6
  435. infrahub_server-1.2.0.dist-info/RECORD +746 -0
  436. infrahub_testcontainers/container.py +5 -6
  437. infrahub_testcontainers/docker-compose.test.yml +2 -2
  438. infrahub_testcontainers/helpers.py +5 -1
  439. infrahub/core/branch/constants.py +0 -2
  440. infrahub/core/schema/definitions/core.py +0 -2275
  441. infrahub/graphql/query.py +0 -52
  442. infrahub/message_bus/messages/check_repository_checkdefinition.py +0 -20
  443. infrahub/message_bus/messages/check_repository_mergeconflicts.py +0 -16
  444. infrahub/message_bus/messages/check_repository_usercheck.py +0 -26
  445. infrahub/message_bus/messages/event_branch_create.py +0 -11
  446. infrahub/message_bus/messages/event_branch_delete.py +0 -11
  447. infrahub/message_bus/messages/event_branch_rebased.py +0 -9
  448. infrahub/message_bus/messages/event_node_mutated.py +0 -15
  449. infrahub/message_bus/messages/event_schema_update.py +0 -9
  450. infrahub/message_bus/messages/request_artifactdefinition_check.py +0 -17
  451. infrahub/message_bus/messages/request_repository_checks.py +0 -12
  452. infrahub/message_bus/messages/request_repository_userchecks.py +0 -18
  453. infrahub/message_bus/operations/check/repository.py +0 -293
  454. infrahub/message_bus/operations/event/node.py +0 -20
  455. infrahub/message_bus/operations/event/schema.py +0 -17
  456. infrahub/message_bus/operations/requests/artifact_definition.py +0 -148
  457. infrahub/message_bus/operations/requests/repository.py +0 -133
  458. infrahub/schema/constants.py +0 -1
  459. infrahub/schema/tasks.py +0 -76
  460. infrahub/services/adapters/database/__init__.py +0 -9
  461. infrahub/tasks/telemetry.py +0 -127
  462. infrahub/webhook/constants.py +0 -3
  463. infrahub_server-1.1.9.dist-info/RECORD +0 -688
  464. /infrahub/{schema → artifacts}/__init__.py +0 -0
  465. {infrahub_server-1.1.9.dist-info → infrahub_server-1.2.0.dist-info}/LICENSE.txt +0 -0
  466. {infrahub_server-1.1.9.dist-info → infrahub_server-1.2.0.dist-info}/WHEEL +0 -0
  467. {infrahub_server-1.1.9.dist-info → infrahub_server-1.2.0.dist-info}/entry_points.txt +0 -0
infrahub/api/artifact.py CHANGED
@@ -5,7 +5,14 @@ from typing import TYPE_CHECKING
5
5
  from fastapi import APIRouter, Body, Depends, Request, Response
6
6
  from pydantic import BaseModel, Field
7
7
 
8
- from infrahub.api.dependencies import BranchParams, get_branch_params, get_current_user, get_db, get_permission_manager
8
+ from infrahub.api.dependencies import (
9
+ BranchParams,
10
+ get_branch_params,
11
+ get_context,
12
+ get_current_user,
13
+ get_db,
14
+ get_permission_manager,
15
+ )
9
16
  from infrahub.core import registry
10
17
  from infrahub.core.account import ObjectPermission
11
18
  from infrahub.core.constants import GLOBAL_BRANCH_NAME, InfrahubKind, PermissionAction
@@ -19,7 +26,9 @@ from infrahub.workflows.catalogue import REQUEST_ARTIFACT_DEFINITION_GENERATE
19
26
 
20
27
  if TYPE_CHECKING:
21
28
  from infrahub.auth import AccountSession
29
+ from infrahub.context import InfrahubContext
22
30
  from infrahub.permissions import PermissionManager
31
+ from infrahub.services import InfrahubServices
23
32
 
24
33
  log = get_logger()
25
34
  router = APIRouter(prefix="/artifact")
@@ -57,12 +66,13 @@ async def generate_artifact(
57
66
  request: Request,
58
67
  artifact_definition_id: str,
59
68
  payload: ArtifactGeneratePayload = Body(
60
- ArtifactGeneratePayload(),
69
+ ArtifactGeneratePayload(), # noqa: B008
61
70
  description="Payload of the request, can be used to limit the scope of the query to a specific list of hosts",
62
71
  ),
63
72
  db: InfrahubDatabase = Depends(get_db),
64
73
  branch_params: BranchParams = Depends(get_branch_params),
65
74
  permission_manager: PermissionManager = Depends(get_permission_manager),
75
+ context: InfrahubContext = Depends(get_context),
66
76
  ) -> None:
67
77
  permission_decision = (
68
78
  PermissionDecisionFlag.ALLOW_DEFAULT
@@ -83,7 +93,7 @@ async def generate_artifact(
83
93
  branch=branch_params.branch,
84
94
  )
85
95
 
86
- service = request.app.state.service
96
+ service: InfrahubServices = request.app.state.service
87
97
  model = RequestArtifactDefinitionGenerate(
88
98
  artifact_definition_id=artifact_definition.id,
89
99
  artifact_definition_name=artifact_definition.name.value,
@@ -91,4 +101,6 @@ async def generate_artifact(
91
101
  limit=payload.nodes,
92
102
  )
93
103
 
94
- await service.workflow.submit_workflow(workflow=REQUEST_ARTIFACT_DEFINITION_GENERATE, parameters={"model": model})
104
+ await service.workflow.submit_workflow(
105
+ workflow=REQUEST_ARTIFACT_DEFINITION_GENERATE, context=context, parameters={"model": model}
106
+ )
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, AsyncIterator, Optional
3
+ from typing import TYPE_CHECKING, AsyncIterator
4
4
 
5
5
  from fastapi import Depends, Query, Request
6
6
  from fastapi.security import APIKeyHeader, HTTPAuthorizationCredentials, HTTPBearer
@@ -8,6 +8,7 @@ from pydantic import BaseModel, ConfigDict
8
8
 
9
9
  from infrahub import config
10
10
  from infrahub.auth import AccountSession, authentication_token, validate_jwt_access_token, validate_jwt_refresh_token
11
+ from infrahub.context import InfrahubContext
11
12
  from infrahub.core.branch import Branch # noqa: TC001
12
13
  from infrahub.core.registry import registry
13
14
  from infrahub.core.timestamp import Timestamp
@@ -24,7 +25,7 @@ jwt_scheme = HTTPBearer(auto_error=False)
24
25
  api_key_scheme = APIKeyHeader(name="X-INFRAHUB-KEY", auto_error=False)
25
26
 
26
27
 
27
- async def cookie_auth_scheme(request: Request) -> Optional[str]:
28
+ async def cookie_auth_scheme(request: Request) -> str | None:
28
29
  return request.cookies.get("access_token") # Replace with the actual name of your JWT cookie
29
30
 
30
31
 
@@ -61,7 +62,7 @@ async def get_access_token(
61
62
  async def get_refresh_token(
62
63
  request: Request,
63
64
  db: InfrahubDatabase = Depends(get_db),
64
- jwt_header: Optional[HTTPAuthorizationCredentials] = Depends(jwt_scheme),
65
+ jwt_header: HTTPAuthorizationCredentials | None = Depends(jwt_scheme),
65
66
  ) -> RefreshTokenData:
66
67
  token = None
67
68
 
@@ -82,8 +83,8 @@ async def get_refresh_token(
82
83
 
83
84
  async def get_branch_params(
84
85
  db: InfrahubDatabase = Depends(get_db),
85
- branch_name: Optional[str] = Query(None, alias="branch", description="Name of the branch to use for the query"),
86
- at: Optional[str] = Query(None, description="Time to use for the query, in absolute or relative format"),
86
+ branch_name: str | None = Query(None, alias="branch", description="Name of the branch to use for the query"),
87
+ at: str | None = Query(None, description="Time to use for the query, in absolute or relative format"),
87
88
  ) -> BranchParams:
88
89
  branch = await registry.get_branch(db=db, branch=branch_name)
89
90
 
@@ -92,7 +93,7 @@ async def get_branch_params(
92
93
 
93
94
  async def get_branch_dep(
94
95
  db: InfrahubDatabase = Depends(get_db),
95
- branch_name: Optional[str] = Query(None, alias="branch", description="Name of the branch to use for the query"),
96
+ branch_name: str | None = Query(None, alias="branch", description="Name of the branch to use for the query"),
96
97
  ) -> Branch:
97
98
  return await registry.get_branch(db=db, branch=branch_name)
98
99
 
@@ -133,3 +134,10 @@ async def get_permission_manager(
133
134
  await permission_manager.load_permissions(db=db, branch=branch_params.branch)
134
135
 
135
136
  return permission_manager
137
+
138
+
139
+ async def get_context(
140
+ branch: Branch = Depends(get_branch_dep),
141
+ account_session: AccountSession = Depends(get_current_user),
142
+ ) -> InfrahubContext:
143
+ return InfrahubContext.init(branch=branch, account=account_session)
@@ -1,4 +1,4 @@
1
- from typing import Any, Optional
1
+ from typing import Any
2
2
 
3
3
  from pydantic import BaseModel, ConfigDict, field_validator, model_validator
4
4
 
@@ -9,13 +9,13 @@ from infrahub.core.timestamp import Timestamp
9
9
  class DiffQueryValidated(BaseModel):
10
10
  model_config = ConfigDict(arbitrary_types_allowed=True)
11
11
  branch: Branch
12
- time_from: Optional[str] = None
13
- time_to: Optional[str] = None
12
+ time_from: str | None = None
13
+ time_to: str | None = None
14
14
  branch_only: bool
15
15
 
16
16
  @field_validator("time_from", "time_to", mode="before")
17
17
  @classmethod
18
- def validate_time(cls, value: Optional[str]) -> Optional[str]:
18
+ def validate_time(cls, value: str | None) -> str | None:
19
19
  if not value:
20
20
  return None
21
21
  Timestamp(value)
@@ -24,12 +24,12 @@ class DiffQueryValidated(BaseModel):
24
24
  @model_validator(mode="before")
25
25
  @classmethod
26
26
  def validate_time_from_if_required(cls, values: dict[str, Any]) -> dict[str, Any]:
27
- branch: Optional[Branch] = values.get("branch")
28
- time_from: Optional[Timestamp] = values.get("time_from")
27
+ branch: Branch | None = values.get("branch")
28
+ time_from: Timestamp | None = values.get("time_from")
29
29
  if getattr(branch, "is_default", False) and not time_from:
30
30
  branch_name = getattr(branch, "name", "")
31
31
  raise ValueError(f"time_from is mandatory when diffing on the default branch `{branch_name}`.")
32
- time_to: Optional[Timestamp] = values.get("time_to")
32
+ time_to: Timestamp | None = values.get("time_to")
33
33
  if time_to and time_from and time_to < time_from:
34
34
  raise ValueError("time_from and time_to are not a valid time range")
35
35
  return values
infrahub/api/oauth2.py CHANGED
@@ -22,7 +22,6 @@ if TYPE_CHECKING:
22
22
  from infrahub.database import InfrahubDatabase
23
23
  from infrahub.services import InfrahubServices
24
24
 
25
- # pylint: disable=R0801
26
25
 
27
26
  log = get_logger()
28
27
  router = APIRouter(prefix="/oauth2")
infrahub/api/oidc.py CHANGED
@@ -24,7 +24,6 @@ if TYPE_CHECKING:
24
24
  from infrahub.database import InfrahubDatabase
25
25
  from infrahub.services import InfrahubServices
26
26
 
27
- # pylint: disable=R0801
28
27
 
29
28
  log = get_logger()
30
29
  router = APIRouter(prefix="/oidc")
infrahub/api/query.py CHANGED
@@ -7,6 +7,7 @@ from graphql import graphql
7
7
  from pydantic import BaseModel, Field
8
8
 
9
9
  from infrahub.api.dependencies import BranchParams, get_branch_params, get_current_user, get_db
10
+ from infrahub.context import InfrahubContext
10
11
  from infrahub.core import registry
11
12
  from infrahub.core.constants import InfrahubKind
12
13
  from infrahub.core.protocols import CoreGraphQLQuery
@@ -57,12 +58,21 @@ async def execute_query(
57
58
  db=db, id=query_id, kind=CoreGraphQLQuery, branch=branch_params.branch, at=branch_params.at
58
59
  )
59
60
 
61
+ context = InfrahubContext.init(branch=branch_params.branch, account=account_session)
62
+
60
63
  gql_params = await prepare_graphql_params(
61
- db=db, branch=branch_params.branch, at=branch_params.at, account_session=account_session
64
+ db=db,
65
+ branch=branch_params.branch,
66
+ at=branch_params.at,
67
+ account_session=account_session,
68
+ service=request.app.state.service,
62
69
  )
70
+ schema_branch = db.schema.get_schema_branch(name=branch_params.branch.name)
71
+
63
72
  analyzed_query = InfrahubGraphQLQueryAnalyzer(
64
73
  query=gql_query.query.value,
65
74
  schema=gql_params.schema,
75
+ schema_branch=schema_branch,
66
76
  branch=branch_params.branch,
67
77
  )
68
78
  await permission_checker.check(
@@ -97,9 +107,7 @@ async def execute_query(
97
107
  GRAPHQL_QUERY_HEIGHT_METRICS.labels(**labels).observe(await analyzed_query.calculate_height())
98
108
  GRAPHQL_QUERY_VARS_METRICS.labels(**labels).observe(len(analyzed_query.variables))
99
109
  GRAPHQL_TOP_LEVEL_QUERIES_METRICS.labels(**labels).observe(analyzed_query.nbr_queries)
100
- GRAPHQL_QUERY_OBJECTS_METRICS.labels(**labels).observe(
101
- len(await analyzed_query.get_models_in_use(types=gql_params.context.types))
102
- )
110
+ GRAPHQL_QUERY_OBJECTS_METRICS.labels(**labels).observe(len(analyzed_query.query_report.impacted_models))
103
111
 
104
112
  response_payload: dict[str, Any] = {"data": data}
105
113
 
@@ -111,11 +119,13 @@ async def execute_query(
111
119
  branch=branch_params.branch.name,
112
120
  query_id=gql_query.id,
113
121
  query_name=gql_query.name.value,
114
- related_node_ids=sorted(list(related_node_ids)),
122
+ related_node_ids=sorted(related_node_ids),
115
123
  subscribers=sorted(subscribers),
116
124
  params=params,
117
125
  )
118
- await service.workflow.submit_workflow(workflow=GRAPHQL_QUERY_GROUP_UPDATE, parameters={"model": model})
126
+ await service.workflow.submit_workflow(
127
+ workflow=GRAPHQL_QUERY_GROUP_UPDATE, context=context, parameters={"model": model}
128
+ )
119
129
 
120
130
  return response_payload
121
131
 
@@ -124,7 +134,8 @@ async def execute_query(
124
134
  async def graphql_query_post(
125
135
  request: Request,
126
136
  payload: QueryPayload = Body(
127
- QueryPayload(), description="Payload of the request, must be used to provide the variables"
137
+ QueryPayload(), # noqa: B008
138
+ description="Payload of the request, must be used to provide the variables",
128
139
  ),
129
140
  query_id: str = Path(description="ID or Name of the GraphQL query to execute"),
130
141
  subscribers: list[str] = Query(
infrahub/api/schema.py CHANGED
@@ -13,7 +13,7 @@ from pydantic import (
13
13
  from starlette.responses import JSONResponse
14
14
 
15
15
  from infrahub import lock
16
- from infrahub.api.dependencies import get_branch_dep, get_current_user, get_db, get_permission_manager
16
+ from infrahub.api.dependencies import get_branch_dep, get_context, get_current_user, get_db, get_permission_manager
17
17
  from infrahub.api.exceptions import SchemaNotValidError
18
18
  from infrahub.core import registry
19
19
  from infrahub.core.account import GlobalPermission
@@ -25,7 +25,7 @@ from infrahub.core.models import ( # noqa: TC001
25
25
  SchemaDiff,
26
26
  SchemaUpdateValidationResult,
27
27
  )
28
- from infrahub.core.schema import GenericSchema, MainSchemaTypes, NodeSchema, ProfileSchema, SchemaRoot
28
+ from infrahub.core.schema import GenericSchema, MainSchemaTypes, NodeSchema, ProfileSchema, SchemaRoot, TemplateSchema
29
29
  from infrahub.core.schema.constants import SchemaNamespace # noqa: TC001
30
30
  from infrahub.core.validators.models.validate_migration import (
31
31
  SchemaValidateMigrationData,
@@ -44,6 +44,7 @@ if TYPE_CHECKING:
44
44
  from typing_extensions import Self
45
45
 
46
46
  from infrahub.auth import AccountSession
47
+ from infrahub.context import InfrahubContext
47
48
  from infrahub.core.schema.schema_branch import SchemaBranch
48
49
  from infrahub.permissions import PermissionManager
49
50
  from infrahub.services import InfrahubServices
@@ -67,7 +68,7 @@ class APISchemaMixin:
67
68
  @classmethod
68
69
  def set_kind(cls, values: Any) -> Any:
69
70
  if isinstance(values, dict):
70
- values["kind"] = f'{values["namespace"]}{values["name"]}'
71
+ values["kind"] = f"{values['namespace']}{values['name']}"
71
72
  return values
72
73
 
73
74
 
@@ -86,11 +87,17 @@ class APIProfileSchema(ProfileSchema, APISchemaMixin):
86
87
  hash: str
87
88
 
88
89
 
90
+ class APITemplateSchema(TemplateSchema, APISchemaMixin):
91
+ api_kind: str | None = Field(default=None, alias="kind", validate_default=True)
92
+ hash: str
93
+
94
+
89
95
  class SchemaReadAPI(BaseModel):
90
96
  main: str = Field(description="Main hash for the entire schema")
91
97
  nodes: list[APINodeSchema] = Field(default_factory=list)
92
98
  generics: list[APIGenericSchema] = Field(default_factory=list)
93
99
  profiles: list[APIProfileSchema] = Field(default_factory=list)
100
+ templates: list[APITemplateSchema] = Field(default_factory=list)
94
101
  namespaces: list[SchemaNamespace] = Field(default_factory=list)
95
102
 
96
103
 
@@ -190,6 +197,11 @@ async def get_schema(
190
197
  for value in all_schemas
191
198
  if isinstance(value, ProfileSchema) and value.namespace != "Internal"
192
199
  ],
200
+ templates=[
201
+ APITemplateSchema.from_schema(value)
202
+ for value in all_schemas
203
+ if isinstance(value, TemplateSchema) and value.namespace != "Internal"
204
+ ],
193
205
  namespaces=schema_branch.get_namespaces(),
194
206
  )
195
207
 
@@ -206,15 +218,16 @@ async def get_schema_summary(
206
218
  @router.get("/{schema_kind}")
207
219
  async def get_schema_by_kind(
208
220
  schema_kind: str, branch: Branch = Depends(get_branch_dep), _: AccountSession = Depends(get_current_user)
209
- ) -> APIProfileSchema | APINodeSchema | APIGenericSchema:
221
+ ) -> APIProfileSchema | APINodeSchema | APIGenericSchema | APITemplateSchema:
210
222
  log.debug("schema_kind_request", branch=branch.name)
211
223
 
212
224
  schema = registry.schema.get(name=schema_kind, branch=branch, duplicate=False)
213
225
 
214
- api_schema: dict[str, type[APIProfileSchema | APINodeSchema | APIGenericSchema]] = {
226
+ api_schema: dict[str, type[APIProfileSchema | APINodeSchema | APIGenericSchema | APITemplateSchema]] = {
215
227
  "profile": APIProfileSchema,
216
228
  "node": APINodeSchema,
217
229
  "generic": APIGenericSchema,
230
+ "template": APITemplateSchema,
218
231
  }
219
232
  key = ""
220
233
 
@@ -224,6 +237,8 @@ async def get_schema_by_kind(
224
237
  key = "node"
225
238
  if isinstance(schema, GenericSchema):
226
239
  key = "generic"
240
+ if isinstance(schema, TemplateSchema):
241
+ key = "template"
227
242
 
228
243
  return api_schema[key].from_schema(schema=schema)
229
244
 
@@ -269,6 +284,7 @@ async def load_schema(
269
284
  branch: Branch = Depends(get_branch_dep),
270
285
  account_session: AccountSession = Depends(get_current_user),
271
286
  permission_manager: PermissionManager = Depends(get_permission_manager),
287
+ context: InfrahubContext = Depends(get_context),
272
288
  ) -> SchemaUpdate:
273
289
  permission_manager.raise_for_permission(
274
290
  permission=GlobalPermission(
@@ -317,6 +333,7 @@ async def load_schema(
317
333
  )
318
334
  responses = await service.workflow.execute_workflow(
319
335
  workflow=SCHEMA_VALIDATE_MIGRATION,
336
+ context=context,
320
337
  expected_return=list[SchemaValidatorPathResponseData],
321
338
  parameters={"message": validate_migration_data},
322
339
  )
@@ -361,6 +378,7 @@ async def load_schema(
361
378
  )
362
379
  migration_error_msgs = await service.workflow.execute_workflow(
363
380
  workflow=SCHEMA_APPLY_MIGRATION,
381
+ context=context,
364
382
  expected_return=list[str],
365
383
  parameters={"message": apply_migration_data},
366
384
  )
@@ -373,9 +391,15 @@ async def load_schema(
373
391
  log_data = get_log_data()
374
392
  request_id = log_data.get("request_id", "")
375
393
  event = SchemaUpdatedEvent(
376
- branch=branch.name,
394
+ branch_name=branch.name,
377
395
  schema_hash=branch.active_schema_hash.main,
378
- meta=EventMeta(initiator_id=WORKER_IDENTITY, request_id=request_id, account_id=account_session.account_id),
396
+ meta=EventMeta(
397
+ initiator_id=WORKER_IDENTITY,
398
+ request_id=request_id,
399
+ account_id=account_session.account_id,
400
+ branch=branch,
401
+ context=context,
402
+ ),
379
403
  )
380
404
  await service.event.send(event=event)
381
405
 
@@ -387,6 +411,7 @@ async def check_schema(
387
411
  request: Request,
388
412
  schemas: SchemasLoadAPI,
389
413
  branch: Branch = Depends(get_branch_dep),
414
+ context: InfrahubContext = Depends(get_context),
390
415
  _: AccountSession = Depends(get_current_user),
391
416
  ) -> JSONResponse:
392
417
  service: InfrahubServices = request.app.state.service
@@ -413,6 +438,7 @@ async def check_schema(
413
438
  )
414
439
  responses = await service.workflow.execute_workflow(
415
440
  workflow=SCHEMA_VALIDATE_MIGRATION,
441
+ context=context,
416
442
  expected_return=list[SchemaValidatorPathResponseData],
417
443
  parameters={"message": validate_migration_data},
418
444
  )
@@ -9,6 +9,7 @@ from starlette.responses import JSONResponse, PlainTextResponse
9
9
  from infrahub.api.dependencies import (
10
10
  BranchParams,
11
11
  get_branch_params,
12
+ get_context,
12
13
  get_current_user,
13
14
  get_db,
14
15
  )
@@ -28,8 +29,8 @@ from infrahub.workflows.catalogue import TRANSFORM_JINJA2_RENDER, TRANSFORM_PYTH
28
29
 
29
30
  if TYPE_CHECKING:
30
31
  from infrahub.auth import AccountSession
32
+ from infrahub.context import InfrahubContext
31
33
  from infrahub.services import InfrahubServices
32
-
33
34
  router = APIRouter()
34
35
 
35
36
 
@@ -38,6 +39,7 @@ async def transform_python(
38
39
  request: Request,
39
40
  transform_id: str,
40
41
  db: InfrahubDatabase = Depends(get_db),
42
+ context: InfrahubContext = Depends(get_context),
41
43
  branch_params: BranchParams = Depends(get_branch_params),
42
44
  _: AccountSession = Depends(get_current_user),
43
45
  ) -> JSONResponse:
@@ -62,7 +64,9 @@ async def transform_python(
62
64
  message="Repository doesn't have a commit",
63
65
  )
64
66
 
65
- gql_params = await prepare_graphql_params(db=request.app.state.db, branch=branch_params.branch, at=branch_params.at)
67
+ gql_params = await prepare_graphql_params(
68
+ db=request.app.state.db, branch=branch_params.branch, at=branch_params.at, service=request.app.state.service
69
+ )
66
70
 
67
71
  result = await graphql(
68
72
  schema=gql_params.schema,
@@ -88,7 +92,7 @@ async def transform_python(
88
92
  )
89
93
 
90
94
  response = await service.workflow.execute_workflow(
91
- workflow=TRANSFORM_PYTHON_RENDER, parameters={"message": message}
95
+ workflow=TRANSFORM_PYTHON_RENDER, context=context, parameters={"message": message}
92
96
  )
93
97
  return JSONResponse(content=response)
94
98
 
@@ -99,6 +103,7 @@ async def transform_jinja2(
99
103
  transform_id: str = Path(description="ID or Name of the Jinja2 Transform to render"),
100
104
  db: InfrahubDatabase = Depends(get_db),
101
105
  branch_params: BranchParams = Depends(get_branch_params),
106
+ context: InfrahubContext = Depends(get_context),
102
107
  _: AccountSession = Depends(get_current_user),
103
108
  ) -> PlainTextResponse:
104
109
  params = {key: value for key, value in request.query_params.items() if key not in ["branch", "at"]}
@@ -122,7 +127,9 @@ async def transform_jinja2(
122
127
  message="Repository doesn't have a commit",
123
128
  )
124
129
 
125
- gql_params = await prepare_graphql_params(db=request.app.state.db, branch=branch_params.branch, at=branch_params.at)
130
+ gql_params = await prepare_graphql_params(
131
+ db=request.app.state.db, branch=branch_params.branch, at=branch_params.at, service=request.app.state.service
132
+ )
126
133
 
127
134
  result = await graphql(
128
135
  schema=gql_params.schema,
@@ -148,6 +155,6 @@ async def transform_jinja2(
148
155
  service: InfrahubServices = request.app.state.service
149
156
 
150
157
  response = await service.workflow.execute_workflow(
151
- workflow=TRANSFORM_JINJA2_RENDER, expected_return=str, parameters={"message": message}
158
+ workflow=TRANSFORM_JINJA2_RENDER, context=context, expected_return=str, parameters={"message": message}
152
159
  )
153
160
  return PlainTextResponse(content=response)
@@ -1,11 +1,9 @@
1
- from typing import Optional
1
+ from pydantic import BaseModel, Field
2
2
 
3
- from pydantic import Field
3
+ from infrahub.context import InfrahubContext
4
4
 
5
- from infrahub.message_bus import InfrahubMessage
6
5
 
7
-
8
- class CheckArtifactCreate(InfrahubMessage):
6
+ class CheckArtifactCreate(BaseModel):
9
7
  """Runs a check to verify the creation of an artifact."""
10
8
 
11
9
  artifact_name: str = Field(..., description="Name of the artifact")
@@ -19,9 +17,11 @@ class CheckArtifactCreate(InfrahubMessage):
19
17
  repository_kind: str = Field(..., description="The kind of the Repository")
20
18
  branch_name: str = Field(..., description="The branch where the check is run")
21
19
  target_id: str = Field(..., description="The ID of the target object for this artifact")
20
+ target_kind: str = Field(..., description="The kind of the target object for this artifact")
22
21
  target_name: str = Field(..., description="Name of the artifact target")
23
- artifact_id: Optional[str] = Field(default=None, description="The id of the artifact if it previously existed")
22
+ artifact_id: str | None = Field(default=None, description="The id of the artifact if it previously existed")
24
23
  query: str = Field(..., description="The name of the query to use when collecting data")
25
24
  timeout: int = Field(..., description="Timeout for requests used to generate this artifact")
26
25
  variables: dict = Field(..., description="Input variables when generating the artifact")
27
26
  validator_id: str = Field(..., description="The ID of the validator")
27
+ context: InfrahubContext = Field(..., description="The context of the task")
@@ -1,41 +1,39 @@
1
- from typing import Union
2
-
3
1
  from prefect import flow
4
2
 
3
+ from infrahub.artifacts.models import CheckArtifactCreate
5
4
  from infrahub.core.constants import InfrahubKind, ValidatorConclusion
6
5
  from infrahub.core.timestamp import Timestamp
7
- from infrahub.git.repository import InfrahubReadOnlyRepository, InfrahubRepository
8
- from infrahub.log import get_logger
9
- from infrahub.message_bus import messages
6
+ from infrahub.git import InfrahubReadOnlyRepository, InfrahubRepository
10
7
  from infrahub.services import InfrahubServices
11
8
  from infrahub.tasks.artifact import define_artifact
12
- from infrahub.tasks.check import set_check_status
13
9
  from infrahub.workflows.utils import add_tags
14
10
 
15
- log = get_logger()
16
-
17
11
 
18
12
  @flow(name="git-repository-check-artifact-create", flow_run_name="Check artifact creation")
19
- async def create(message: messages.CheckArtifactCreate, service: InfrahubServices) -> None:
20
- await add_tags(branches=[message.branch_name], nodes=[message.target_id])
21
- validator = await service.client.get(
22
- kind=InfrahubKind.ARTIFACTVALIDATOR, id=message.validator_id, include=["checks"]
23
- )
13
+ async def create(model: CheckArtifactCreate, service: InfrahubServices) -> ValidatorConclusion:
14
+ await add_tags(branches=[model.branch_name], nodes=[model.target_id])
15
+ validator = await service.client.get(kind=InfrahubKind.ARTIFACTVALIDATOR, id=model.validator_id, include=["checks"])
24
16
 
17
+ repo: InfrahubReadOnlyRepository | InfrahubRepository
25
18
  if InfrahubKind.READONLYREPOSITORY:
26
19
  repo = await InfrahubReadOnlyRepository.init(
27
- id=message.repository_id, name=message.repository_name, client=service.client
20
+ id=model.repository_id,
21
+ name=model.repository_name,
22
+ client=service.client,
23
+ service=service,
28
24
  )
29
25
  else:
30
26
  repo = await InfrahubRepository.init(
31
- id=message.repository_id, name=message.repository_name, client=service.client
27
+ id=model.repository_id,
28
+ name=model.repository_name,
29
+ client=service.client,
30
+ service=service,
32
31
  )
33
32
 
34
- artifact = await define_artifact(message=message, service=service)
33
+ artifact, artifact_created = await define_artifact(model=model, service=service)
35
34
 
36
- conclusion = ValidatorConclusion.SUCCESS.value
37
35
  severity = "info"
38
- artifact_result: dict[str, Union[str, bool, None]] = {
36
+ artifact_result: dict[str, str | bool | None] = {
39
37
  "changed": None,
40
38
  "checksum": None,
41
39
  "artifact_id": None,
@@ -44,22 +42,23 @@ async def create(message: messages.CheckArtifactCreate, service: InfrahubService
44
42
  check_message = "Failed to render artifact"
45
43
 
46
44
  try:
47
- result = await repo.render_artifact(artifact=artifact, message=message)
45
+ result = await repo.render_artifact(artifact=artifact, artifact_created=artifact_created, message=model)
48
46
  artifact_result["changed"] = result.changed
49
47
  artifact_result["checksum"] = result.checksum
50
48
  artifact_result["artifact_id"] = result.artifact_id
51
49
  artifact_result["storage_id"] = result.storage_id
52
50
  check_message = "Artifact rendered successfully"
51
+ conclusion = ValidatorConclusion.SUCCESS
53
52
 
54
- except Exception as exc: # pylint: disable=broad-except
55
- conclusion = ValidatorConclusion.FAILURE.value
53
+ except Exception as exc:
56
54
  artifact.status.value = "Error"
55
+ await artifact.save()
57
56
  severity = "critical"
57
+ conclusion = ValidatorConclusion.FAILURE
58
58
  check_message += f": {str(exc)}"
59
- await artifact.save()
60
59
 
61
60
  check = None
62
- check_name = f"{message.artifact_name}: {message.target_name}"
61
+ check_name = f"{model.artifact_name}: {model.target_name}"
63
62
  existing_check = await service.client.filters(
64
63
  kind=InfrahubKind.ARTIFACTCHECK, validator__ids=validator.id, name__value=check_name
65
64
  )
@@ -68,7 +67,7 @@ async def create(message: messages.CheckArtifactCreate, service: InfrahubService
68
67
 
69
68
  if check:
70
69
  check.created_at.value = Timestamp().to_string()
71
- check.conclusion.value = conclusion
70
+ check.conclusion.value = conclusion.value
72
71
  check.severity.value = severity
73
72
  check.changed.value = artifact_result["changed"]
74
73
  check.checksum.value = artifact_result["checksum"]
@@ -80,12 +79,12 @@ async def create(message: messages.CheckArtifactCreate, service: InfrahubService
80
79
  kind=InfrahubKind.ARTIFACTCHECK,
81
80
  data={
82
81
  "name": check_name,
83
- "origin": message.repository_id,
82
+ "origin": model.repository_id,
84
83
  "kind": "ArtifactDefinition",
85
- "validator": message.validator_id,
84
+ "validator": model.validator_id,
86
85
  "created_at": Timestamp().to_string(),
87
86
  "message": check_message,
88
- "conclusion": conclusion,
87
+ "conclusion": conclusion.value,
89
88
  "severity": severity,
90
89
  "changed": artifact_result["changed"],
91
90
  "checksum": artifact_result["checksum"],
@@ -95,4 +94,4 @@ async def create(message: messages.CheckArtifactCreate, service: InfrahubService
95
94
  )
96
95
  await check.save()
97
96
 
98
- await set_check_status(message=message, conclusion=conclusion, service=service)
97
+ return conclusion
infrahub/cli/__init__.py CHANGED
@@ -1,20 +1,21 @@
1
1
  from asyncio import run as aiorun
2
2
 
3
3
  import typer
4
+ from infrahub_sdk.async_typer import AsyncTyper
4
5
 
5
6
  from infrahub import config
6
- from infrahub.cli.context import CliContext
7
- from infrahub.cli.db import app as db_app
8
- from infrahub.cli.events import app as events_app
9
- from infrahub.cli.git_agent import app as git_app
10
- from infrahub.cli.server import app as server_app
11
- from infrahub.cli.tasks import app as tasks_app
12
7
  from infrahub.core.initialization import initialization
13
8
  from infrahub.database import InfrahubDatabase, get_db
14
9
 
15
- # pylint: disable=import-outside-toplevel
10
+ from .context import CliContext
11
+ from .db import app as db_app
12
+ from .events import app as events_app
13
+ from .git_agent import app as git_app
14
+ from .server import app as server_app
15
+ from .tasks import app as tasks_app
16
+ from .upgrade import upgrade_cmd
16
17
 
17
- app = typer.Typer(name="Infrahub CLI", pretty_exceptions_enable=False)
18
+ app = AsyncTyper(name="Infrahub CLI", pretty_exceptions_enable=False)
18
19
 
19
20
 
20
21
  @app.callback()
@@ -24,10 +25,11 @@ def common(ctx: typer.Context) -> None:
24
25
 
25
26
 
26
27
  app.add_typer(server_app, name="server")
27
- app.add_typer(git_app, name="git-agent")
28
+ app.add_typer(git_app, name="git-agent", hidden=True)
28
29
  app.add_typer(db_app, name="db")
29
- app.add_typer(events_app, name="events", help="Interact with the events system.")
30
+ app.add_typer(events_app, name="events", help="Interact with the events system.", hidden=True)
30
31
  app.add_typer(tasks_app, name="tasks", hidden=True)
32
+ app.command(name="upgrade")(upgrade_cmd)
31
33
 
32
34
 
33
35
  async def _init_shell(config_file: str) -> None:
@@ -0,0 +1,3 @@
1
+ ERROR_BADGE = "[bold red]ERROR[/bold red]"
2
+ SUCCESS_BADGE = "[green]SUCCESS[/green]"
3
+ FAILED_BADGE = "[bold red]FAILED[/bold red]"