infrahub-server 1.2.0rc0__py3-none-any.whl → 1.2.1__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 (365) hide show
  1. infrahub/api/dependencies.py +6 -6
  2. infrahub/api/diff/validation_models.py +7 -7
  3. infrahub/api/schema.py +1 -1
  4. infrahub/artifacts/models.py +5 -3
  5. infrahub/artifacts/tasks.py +3 -5
  6. infrahub/cli/__init__.py +13 -9
  7. infrahub/cli/constants.py +3 -0
  8. infrahub/cli/db.py +165 -183
  9. infrahub/cli/upgrade.py +146 -0
  10. infrahub/computed_attribute/gather.py +185 -0
  11. infrahub/computed_attribute/models.py +240 -12
  12. infrahub/computed_attribute/tasks.py +77 -441
  13. infrahub/computed_attribute/triggers.py +13 -47
  14. infrahub/config.py +43 -32
  15. infrahub/context.py +14 -0
  16. infrahub/core/account.py +4 -4
  17. infrahub/core/attribute.py +58 -58
  18. infrahub/core/branch/tasks.py +74 -22
  19. infrahub/core/changelog/diff.py +95 -36
  20. infrahub/core/changelog/models.py +217 -43
  21. infrahub/core/constants/__init__.py +28 -0
  22. infrahub/core/constants/infrahubkind.py +2 -0
  23. infrahub/core/constants/schema.py +2 -0
  24. infrahub/core/constraint/node/runner.py +9 -8
  25. infrahub/core/diff/branch_differ.py +10 -10
  26. infrahub/core/diff/enricher/cardinality_one.py +5 -0
  27. infrahub/core/diff/enricher/hierarchy.py +17 -4
  28. infrahub/core/diff/enricher/labels.py +5 -0
  29. infrahub/core/diff/enricher/path_identifier.py +4 -0
  30. infrahub/core/diff/ipam_diff_parser.py +4 -5
  31. infrahub/core/diff/model/diff.py +27 -27
  32. infrahub/core/diff/model/path.py +32 -9
  33. infrahub/core/diff/parent_node_adder.py +78 -0
  34. infrahub/core/diff/payload_builder.py +13 -2
  35. infrahub/core/diff/query/filters.py +2 -2
  36. infrahub/core/diff/query/merge.py +20 -17
  37. infrahub/core/diff/query/save.py +188 -182
  38. infrahub/core/diff/query/summary_counts_enricher.py +51 -4
  39. infrahub/core/diff/query_parser.py +4 -4
  40. infrahub/core/diff/repository/deserializer.py +8 -3
  41. infrahub/core/diff/repository/repository.py +156 -38
  42. infrahub/core/diff/tasks.py +4 -4
  43. infrahub/core/graph/__init__.py +1 -1
  44. infrahub/core/graph/index.py +3 -0
  45. infrahub/core/initialization.py +1 -10
  46. infrahub/core/ipam/constants.py +3 -4
  47. infrahub/core/ipam/reconciler.py +12 -12
  48. infrahub/core/ipam/utilization.py +10 -13
  49. infrahub/core/manager.py +36 -36
  50. infrahub/core/merge.py +7 -7
  51. infrahub/core/migrations/__init__.py +2 -3
  52. infrahub/core/migrations/graph/__init__.py +12 -3
  53. infrahub/core/migrations/graph/m017_add_core_profile.py +1 -5
  54. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +4 -4
  55. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
  56. infrahub/core/migrations/graph/m020_duplicate_edges.py +160 -0
  57. infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +51 -0
  58. infrahub/core/migrations/graph/m022_add_generate_template_attr.py +48 -0
  59. infrahub/core/migrations/graph/m023_deduplicate_cardinality_one_relationships.py +96 -0
  60. infrahub/core/migrations/query/attribute_add.py +2 -2
  61. infrahub/core/migrations/query/node_duplicate.py +43 -26
  62. infrahub/core/migrations/query/schema_attribute_update.py +2 -2
  63. infrahub/core/migrations/schema/models.py +19 -4
  64. infrahub/core/migrations/schema/node_remove.py +26 -12
  65. infrahub/core/migrations/schema/tasks.py +2 -2
  66. infrahub/core/migrations/shared.py +16 -16
  67. infrahub/core/models.py +15 -6
  68. infrahub/core/node/__init__.py +43 -39
  69. infrahub/core/node/base.py +2 -4
  70. infrahub/core/node/constraints/attribute_uniqueness.py +2 -2
  71. infrahub/core/node/constraints/grouped_uniqueness.py +99 -47
  72. infrahub/core/node/constraints/interface.py +1 -2
  73. infrahub/core/node/delete_validator.py +3 -5
  74. infrahub/core/node/ipam.py +4 -4
  75. infrahub/core/node/permissions.py +7 -7
  76. infrahub/core/node/resource_manager/ip_address_pool.py +6 -6
  77. infrahub/core/node/resource_manager/ip_prefix_pool.py +6 -6
  78. infrahub/core/node/resource_manager/number_pool.py +3 -3
  79. infrahub/core/path.py +12 -12
  80. infrahub/core/property.py +11 -11
  81. infrahub/core/protocols.py +7 -0
  82. infrahub/core/protocols_base.py +21 -21
  83. infrahub/core/query/__init__.py +33 -33
  84. infrahub/core/query/attribute.py +6 -4
  85. infrahub/core/query/diff.py +3 -3
  86. infrahub/core/query/node.py +82 -32
  87. infrahub/core/query/relationship.py +228 -40
  88. infrahub/core/query/resource_manager.py +2 -0
  89. infrahub/core/query/standard_node.py +3 -3
  90. infrahub/core/query/subquery.py +9 -9
  91. infrahub/core/registry.py +13 -15
  92. infrahub/core/relationship/constraints/count.py +3 -4
  93. infrahub/core/relationship/constraints/peer_kind.py +3 -4
  94. infrahub/core/relationship/constraints/profiles_kind.py +2 -2
  95. infrahub/core/relationship/model.py +51 -59
  96. infrahub/core/schema/attribute_schema.py +16 -8
  97. infrahub/core/schema/basenode_schema.py +105 -44
  98. infrahub/core/schema/computed_attribute.py +3 -3
  99. infrahub/core/schema/definitions/core/__init__.py +147 -0
  100. infrahub/core/schema/definitions/core/account.py +171 -0
  101. infrahub/core/schema/definitions/core/artifact.py +136 -0
  102. infrahub/core/schema/definitions/core/builtin.py +24 -0
  103. infrahub/core/schema/definitions/core/check.py +68 -0
  104. infrahub/core/schema/definitions/core/core.py +17 -0
  105. infrahub/core/schema/definitions/core/generator.py +100 -0
  106. infrahub/core/schema/definitions/core/graphql_query.py +79 -0
  107. infrahub/core/schema/definitions/core/group.py +108 -0
  108. infrahub/core/schema/definitions/core/ipam.py +193 -0
  109. infrahub/core/schema/definitions/core/lineage.py +19 -0
  110. infrahub/core/schema/definitions/core/menu.py +48 -0
  111. infrahub/core/schema/definitions/core/permission.py +163 -0
  112. infrahub/core/schema/definitions/core/profile.py +18 -0
  113. infrahub/core/schema/definitions/core/propose_change.py +97 -0
  114. infrahub/core/schema/definitions/core/propose_change_comment.py +193 -0
  115. infrahub/core/schema/definitions/core/propose_change_validator.py +328 -0
  116. infrahub/core/schema/definitions/core/repository.py +286 -0
  117. infrahub/core/schema/definitions/core/resource_pool.py +170 -0
  118. infrahub/core/schema/definitions/core/template.py +27 -0
  119. infrahub/core/schema/definitions/core/transform.py +96 -0
  120. infrahub/core/schema/definitions/core/webhook.py +134 -0
  121. infrahub/core/schema/definitions/internal.py +16 -16
  122. infrahub/core/schema/dropdown.py +3 -4
  123. infrahub/core/schema/generated/attribute_schema.py +15 -18
  124. infrahub/core/schema/generated/base_node_schema.py +12 -14
  125. infrahub/core/schema/generated/node_schema.py +3 -5
  126. infrahub/core/schema/generated/relationship_schema.py +9 -11
  127. infrahub/core/schema/generic_schema.py +2 -2
  128. infrahub/core/schema/manager.py +20 -9
  129. infrahub/core/schema/node_schema.py +4 -2
  130. infrahub/core/schema/relationship_schema.py +14 -6
  131. infrahub/core/schema/schema_branch.py +292 -144
  132. infrahub/core/schema/schema_branch_computed.py +41 -4
  133. infrahub/core/task/task.py +3 -3
  134. infrahub/core/task/user_task.py +15 -15
  135. infrahub/core/timestamp.py +3 -3
  136. infrahub/core/utils.py +20 -18
  137. infrahub/core/validators/__init__.py +1 -3
  138. infrahub/core/validators/aggregated_checker.py +2 -2
  139. infrahub/core/validators/attribute/choices.py +2 -2
  140. infrahub/core/validators/attribute/enum.py +2 -2
  141. infrahub/core/validators/attribute/kind.py +2 -2
  142. infrahub/core/validators/attribute/length.py +2 -2
  143. infrahub/core/validators/attribute/optional.py +2 -2
  144. infrahub/core/validators/attribute/regex.py +2 -2
  145. infrahub/core/validators/attribute/unique.py +2 -2
  146. infrahub/core/validators/checks_runner.py +25 -2
  147. infrahub/core/validators/determiner.py +1 -3
  148. infrahub/core/validators/interface.py +6 -2
  149. infrahub/core/validators/model.py +22 -3
  150. infrahub/core/validators/models/validate_migration.py +17 -4
  151. infrahub/core/validators/node/attribute.py +2 -2
  152. infrahub/core/validators/node/generate_profile.py +2 -2
  153. infrahub/core/validators/node/hierarchy.py +3 -5
  154. infrahub/core/validators/node/inherit_from.py +27 -5
  155. infrahub/core/validators/node/relationship.py +2 -2
  156. infrahub/core/validators/relationship/count.py +4 -4
  157. infrahub/core/validators/relationship/optional.py +2 -2
  158. infrahub/core/validators/relationship/peer.py +2 -2
  159. infrahub/core/validators/shared.py +2 -2
  160. infrahub/core/validators/tasks.py +8 -0
  161. infrahub/core/validators/uniqueness/checker.py +22 -21
  162. infrahub/core/validators/uniqueness/index.py +2 -2
  163. infrahub/core/validators/uniqueness/model.py +11 -11
  164. infrahub/database/__init__.py +27 -22
  165. infrahub/database/metrics.py +7 -1
  166. infrahub/dependencies/builder/constraint/grouped/node_runner.py +1 -3
  167. infrahub/dependencies/builder/diff/deserializer.py +3 -1
  168. infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
  169. infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
  170. infrahub/dependencies/component/registry.py +2 -2
  171. infrahub/events/__init__.py +25 -2
  172. infrahub/events/artifact_action.py +64 -0
  173. infrahub/events/branch_action.py +33 -22
  174. infrahub/events/generator.py +71 -0
  175. infrahub/events/group_action.py +51 -21
  176. infrahub/events/models.py +18 -19
  177. infrahub/events/node_action.py +88 -37
  178. infrahub/events/repository_action.py +5 -18
  179. infrahub/events/schema_action.py +4 -9
  180. infrahub/events/utils.py +16 -0
  181. infrahub/events/validator_action.py +55 -0
  182. infrahub/exceptions.py +32 -24
  183. infrahub/generators/models.py +2 -3
  184. infrahub/generators/tasks.py +24 -4
  185. infrahub/git/base.py +7 -7
  186. infrahub/git/integrator.py +48 -24
  187. infrahub/git/models.py +101 -9
  188. infrahub/git/repository.py +3 -3
  189. infrahub/git/tasks.py +408 -6
  190. infrahub/git/utils.py +48 -0
  191. infrahub/git/worktree.py +1 -2
  192. infrahub/git_credential/askpass.py +1 -2
  193. infrahub/graphql/analyzer.py +12 -0
  194. infrahub/graphql/app.py +13 -15
  195. infrahub/graphql/context.py +39 -0
  196. infrahub/graphql/initialization.py +3 -0
  197. infrahub/graphql/loaders/node.py +2 -12
  198. infrahub/graphql/loaders/peers.py +77 -0
  199. infrahub/graphql/loaders/shared.py +13 -0
  200. infrahub/graphql/manager.py +17 -19
  201. infrahub/graphql/mutations/artifact_definition.py +5 -5
  202. infrahub/graphql/mutations/branch.py +26 -1
  203. infrahub/graphql/mutations/computed_attribute.py +9 -5
  204. infrahub/graphql/mutations/diff.py +23 -11
  205. infrahub/graphql/mutations/diff_conflict.py +5 -0
  206. infrahub/graphql/mutations/generator.py +83 -0
  207. infrahub/graphql/mutations/graphql_query.py +5 -5
  208. infrahub/graphql/mutations/ipam.py +54 -74
  209. infrahub/graphql/mutations/main.py +195 -132
  210. infrahub/graphql/mutations/menu.py +7 -7
  211. infrahub/graphql/mutations/models.py +2 -4
  212. infrahub/graphql/mutations/node_getter/by_default_filter.py +10 -10
  213. infrahub/graphql/mutations/node_getter/by_hfid.py +1 -3
  214. infrahub/graphql/mutations/node_getter/by_id.py +1 -3
  215. infrahub/graphql/mutations/node_getter/interface.py +1 -2
  216. infrahub/graphql/mutations/proposed_change.py +7 -7
  217. infrahub/graphql/mutations/relationship.py +93 -19
  218. infrahub/graphql/mutations/repository.py +8 -8
  219. infrahub/graphql/mutations/resource_manager.py +3 -3
  220. infrahub/graphql/mutations/schema.py +19 -4
  221. infrahub/graphql/mutations/webhook.py +137 -0
  222. infrahub/graphql/parser.py +4 -4
  223. infrahub/graphql/permissions.py +1 -10
  224. infrahub/graphql/queries/diff/tree.py +19 -14
  225. infrahub/graphql/queries/event.py +5 -2
  226. infrahub/graphql/queries/ipam.py +2 -2
  227. infrahub/graphql/queries/relationship.py +2 -2
  228. infrahub/graphql/queries/search.py +2 -2
  229. infrahub/graphql/resolvers/many_relationship.py +264 -0
  230. infrahub/graphql/resolvers/resolver.py +13 -110
  231. infrahub/graphql/schema.py +2 -0
  232. infrahub/graphql/subscription/graphql_query.py +2 -0
  233. infrahub/graphql/types/context.py +12 -0
  234. infrahub/graphql/types/event.py +84 -17
  235. infrahub/graphql/types/node.py +2 -2
  236. infrahub/graphql/utils.py +2 -2
  237. infrahub/groups/ancestors.py +29 -0
  238. infrahub/groups/parsers.py +107 -0
  239. infrahub/lock.py +20 -20
  240. infrahub/menu/constants.py +0 -1
  241. infrahub/menu/generator.py +9 -21
  242. infrahub/menu/menu.py +17 -38
  243. infrahub/menu/models.py +117 -16
  244. infrahub/menu/repository.py +111 -0
  245. infrahub/menu/utils.py +5 -8
  246. infrahub/message_bus/__init__.py +11 -13
  247. infrahub/message_bus/messages/__init__.py +1 -21
  248. infrahub/message_bus/messages/check_generator_run.py +3 -3
  249. infrahub/message_bus/messages/finalize_validator_execution.py +3 -0
  250. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +6 -0
  251. infrahub/message_bus/messages/request_generatordefinition_check.py +2 -0
  252. infrahub/message_bus/messages/send_echo_request.py +1 -1
  253. infrahub/message_bus/operations/__init__.py +1 -10
  254. infrahub/message_bus/operations/check/__init__.py +2 -2
  255. infrahub/message_bus/operations/check/generator.py +1 -0
  256. infrahub/message_bus/operations/event/__init__.py +2 -2
  257. infrahub/message_bus/operations/event/worker.py +0 -3
  258. infrahub/message_bus/operations/finalize/validator.py +51 -1
  259. infrahub/message_bus/operations/requests/__init__.py +0 -2
  260. infrahub/message_bus/operations/requests/generator_definition.py +21 -23
  261. infrahub/message_bus/operations/requests/proposed_change.py +14 -10
  262. infrahub/permissions/globals.py +15 -0
  263. infrahub/pools/number.py +2 -4
  264. infrahub/proposed_change/models.py +3 -0
  265. infrahub/proposed_change/tasks.py +58 -45
  266. infrahub/pytest_plugin.py +13 -10
  267. infrahub/server.py +2 -3
  268. infrahub/services/__init__.py +2 -2
  269. infrahub/services/adapters/cache/__init__.py +4 -6
  270. infrahub/services/adapters/cache/nats.py +4 -5
  271. infrahub/services/adapters/cache/redis.py +3 -7
  272. infrahub/services/adapters/event/__init__.py +1 -1
  273. infrahub/services/adapters/message_bus/__init__.py +3 -3
  274. infrahub/services/adapters/message_bus/local.py +2 -2
  275. infrahub/services/adapters/message_bus/nats.py +4 -4
  276. infrahub/services/adapters/message_bus/rabbitmq.py +4 -4
  277. infrahub/services/adapters/workflow/local.py +2 -2
  278. infrahub/services/component.py +5 -5
  279. infrahub/services/protocols.py +7 -7
  280. infrahub/services/scheduler.py +1 -3
  281. infrahub/task_manager/event.py +102 -9
  282. infrahub/task_manager/models.py +27 -7
  283. infrahub/tasks/artifact.py +7 -6
  284. infrahub/telemetry/__init__.py +0 -0
  285. infrahub/telemetry/constants.py +9 -0
  286. infrahub/telemetry/database.py +86 -0
  287. infrahub/telemetry/models.py +65 -0
  288. infrahub/telemetry/task_manager.py +77 -0
  289. infrahub/{tasks/telemetry.py → telemetry/tasks.py} +49 -56
  290. infrahub/telemetry/utils.py +11 -0
  291. infrahub/trace.py +4 -4
  292. infrahub/transformations/tasks.py +2 -2
  293. infrahub/trigger/catalogue.py +4 -6
  294. infrahub/trigger/constants.py +0 -8
  295. infrahub/trigger/models.py +54 -5
  296. infrahub/trigger/setup.py +90 -0
  297. infrahub/trigger/tasks.py +35 -84
  298. infrahub/utils.py +11 -1
  299. infrahub/validators/__init__.py +0 -0
  300. infrahub/validators/events.py +42 -0
  301. infrahub/validators/tasks.py +41 -0
  302. infrahub/webhook/gather.py +17 -0
  303. infrahub/webhook/models.py +176 -44
  304. infrahub/webhook/tasks.py +154 -155
  305. infrahub/webhook/triggers.py +31 -7
  306. infrahub/workers/infrahub_async.py +2 -2
  307. infrahub/workers/utils.py +2 -2
  308. infrahub/workflows/catalogue.py +86 -35
  309. infrahub/workflows/initialization.py +8 -2
  310. infrahub/workflows/models.py +27 -1
  311. infrahub/workflows/utils.py +10 -1
  312. infrahub_sdk/client.py +35 -8
  313. infrahub_sdk/config.py +3 -0
  314. infrahub_sdk/context.py +13 -0
  315. infrahub_sdk/ctl/branch.py +3 -2
  316. infrahub_sdk/ctl/cli_commands.py +5 -1
  317. infrahub_sdk/ctl/utils.py +0 -16
  318. infrahub_sdk/exceptions.py +12 -0
  319. infrahub_sdk/generator.py +4 -1
  320. infrahub_sdk/graphql.py +45 -13
  321. infrahub_sdk/node.py +71 -22
  322. infrahub_sdk/protocols.py +21 -8
  323. infrahub_sdk/protocols_base.py +32 -11
  324. infrahub_sdk/query_groups.py +6 -35
  325. infrahub_sdk/schema/__init__.py +55 -26
  326. infrahub_sdk/schema/main.py +8 -0
  327. infrahub_sdk/task/__init__.py +11 -0
  328. infrahub_sdk/task/constants.py +3 -0
  329. infrahub_sdk/task/exceptions.py +25 -0
  330. infrahub_sdk/task/manager.py +551 -0
  331. infrahub_sdk/task/models.py +74 -0
  332. infrahub_sdk/testing/schemas/animal.py +9 -0
  333. infrahub_sdk/timestamp.py +142 -33
  334. infrahub_sdk/utils.py +29 -1
  335. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/METADATA +8 -6
  336. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/RECORD +349 -293
  337. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/entry_points.txt +1 -0
  338. infrahub_testcontainers/constants.py +2 -0
  339. infrahub_testcontainers/container.py +157 -12
  340. infrahub_testcontainers/docker-compose.test.yml +31 -6
  341. infrahub_testcontainers/helpers.py +18 -73
  342. infrahub_testcontainers/host.py +41 -0
  343. infrahub_testcontainers/measurements.py +93 -0
  344. infrahub_testcontainers/models.py +38 -0
  345. infrahub_testcontainers/performance_test.py +166 -0
  346. infrahub_testcontainers/plugin.py +136 -0
  347. infrahub_testcontainers/prometheus.yml +30 -0
  348. infrahub/core/schema/definitions/core.py +0 -2286
  349. infrahub/message_bus/messages/check_repository_checkdefinition.py +0 -20
  350. infrahub/message_bus/messages/check_repository_mergeconflicts.py +0 -16
  351. infrahub/message_bus/messages/check_repository_usercheck.py +0 -26
  352. infrahub/message_bus/messages/event_branch_create.py +0 -11
  353. infrahub/message_bus/messages/event_branch_delete.py +0 -11
  354. infrahub/message_bus/messages/event_branch_rebased.py +0 -9
  355. infrahub/message_bus/messages/event_node_mutated.py +0 -15
  356. infrahub/message_bus/messages/event_schema_update.py +0 -9
  357. infrahub/message_bus/messages/request_repository_checks.py +0 -12
  358. infrahub/message_bus/messages/request_repository_userchecks.py +0 -18
  359. infrahub/message_bus/operations/check/repository.py +0 -293
  360. infrahub/message_bus/operations/event/node.py +0 -20
  361. infrahub/message_bus/operations/event/schema.py +0 -17
  362. infrahub/message_bus/operations/requests/repository.py +0 -133
  363. infrahub/webhook/constants.py +0 -1
  364. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/LICENSE.txt +0 -0
  365. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/WHEEL +0 -0
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import inspect
4
- from typing import TYPE_CHECKING, Optional, TypeVar
4
+ from typing import TYPE_CHECKING, TypeVar
5
5
 
6
6
  from ..interface import DependencyBuilderContext
7
7
  from .exceptions import UntrackedDependencyError
@@ -17,7 +17,7 @@ T = TypeVar("T")
17
17
 
18
18
 
19
19
  class ComponentDependencyRegistry:
20
- the_instance: Optional[ComponentDependencyRegistry] = None
20
+ the_instance: ComponentDependencyRegistry | None = None
21
21
 
22
22
  def __init__(self) -> None:
23
23
  self._available_components: dict[type, type[DependencyBuilder]] = {}
@@ -1,4 +1,27 @@
1
+ from .artifact_action import ArtifactCreatedEvent, ArtifactUpdatedEvent
2
+ from .branch_action import BranchCreatedEvent, BranchDeletedEvent, BranchMergedEvent, BranchRebasedEvent
3
+ from .group_action import GroupMemberAddedEvent, GroupMemberRemovedEvent
1
4
  from .models import EventMeta, InfrahubEvent
2
- from .node_action import NodeMutatedEvent
5
+ from .node_action import NodeCreatedEvent, NodeDeletedEvent, NodeUpdatedEvent
6
+ from .repository_action import CommitUpdatedEvent
7
+ from .validator_action import ValidatorFailedEvent, ValidatorPassedEvent, ValidatorStartedEvent
3
8
 
4
- __all__ = ["EventMeta", "InfrahubEvent", "NodeMutatedEvent"]
9
+ __all__ = [
10
+ "ArtifactCreatedEvent",
11
+ "ArtifactUpdatedEvent",
12
+ "BranchCreatedEvent",
13
+ "BranchDeletedEvent",
14
+ "BranchMergedEvent",
15
+ "BranchRebasedEvent",
16
+ "CommitUpdatedEvent",
17
+ "EventMeta",
18
+ "GroupMemberAddedEvent",
19
+ "GroupMemberRemovedEvent",
20
+ "InfrahubEvent",
21
+ "NodeCreatedEvent",
22
+ "NodeDeletedEvent",
23
+ "NodeUpdatedEvent",
24
+ "ValidatorFailedEvent",
25
+ "ValidatorPassedEvent",
26
+ "ValidatorStartedEvent",
27
+ ]
@@ -0,0 +1,64 @@
1
+ from typing import ClassVar
2
+
3
+ from pydantic import Field
4
+
5
+ from .constants import EVENT_NAMESPACE
6
+ from .models import InfrahubEvent
7
+
8
+
9
+ class ArtifactEvent(InfrahubEvent):
10
+ """Event generated when an artifact has been created or updated."""
11
+
12
+ node_id: str = Field(..., description="The ID of the artifact")
13
+ artifact_definition_id: str = Field(..., description="The ID of the artifact definition")
14
+ target_id: str = Field(..., description="The ID of the target of the artifact")
15
+ target_kind: str = Field(..., description="The kind of the target of the artifact")
16
+ checksum: str = Field(..., description="The current checksum of the artifact")
17
+ checksum_previous: str | None = Field(default=None, description="The previous checksum of the artifact")
18
+ storage_id: str = Field(..., description="The current storage id of the artifact")
19
+ storage_id_previous: str | None = Field(default=None, description="The previous storage id of the artifact")
20
+
21
+ def get_related(self) -> list[dict[str, str]]:
22
+ related = super().get_related()
23
+ related.append(
24
+ {
25
+ "prefect.resource.id": self.target_id,
26
+ "prefect.resource.role": "infrahub.related.node",
27
+ "infrahub.node.kind": self.target_kind,
28
+ }
29
+ )
30
+ related.append(
31
+ {
32
+ "prefect.resource.id": self.target_id,
33
+ "prefect.resource.role": "infrahub.artifact",
34
+ "infrahub.artifact.checksum": self.checksum,
35
+ "infrahub.artifact.checksum_previous": self.checksum_previous or "",
36
+ "infrahub.artifact.storage_id": self.storage_id,
37
+ "infrahub.artifact.storage_id_previous": self.storage_id_previous or "",
38
+ "infrahub.artifact.artifact_definition_id": self.artifact_definition_id,
39
+ }
40
+ )
41
+
42
+ return related
43
+
44
+ def get_resource(self) -> dict[str, str]:
45
+ return {
46
+ "prefect.resource.id": self.node_id,
47
+ "infrahub.node.kind": "CoreArtifact",
48
+ "infrahub.node.id": self.node_id,
49
+ "infrahub.branch.name": self.meta.context.branch.name,
50
+ }
51
+
52
+
53
+ class ArtifactCreatedEvent(ArtifactEvent):
54
+ """Event generated when an artifact has been created"""
55
+
56
+ event_name: ClassVar[str] = f"{EVENT_NAMESPACE}.artifact.created"
57
+ infrahub_node_kind_event: ClassVar[bool] = True
58
+
59
+
60
+ class ArtifactUpdatedEvent(ArtifactEvent):
61
+ """Event generated when an artifact has been updated"""
62
+
63
+ event_name: ClassVar[str] = f"{EVENT_NAMESPACE}.artifact.updated"
64
+ infrahub_node_kind_event: ClassVar[bool] = True
@@ -1,5 +1,8 @@
1
- from pydantic import Field, computed_field
1
+ from typing import ClassVar
2
2
 
3
+ from pydantic import Field
4
+
5
+ from infrahub.core.constants import InfrahubKind
3
6
  from infrahub.message_bus import InfrahubMessage
4
7
  from infrahub.message_bus.messages.refresh_registry_branches import RefreshRegistryBranches
5
8
  from infrahub.message_bus.messages.refresh_registry_rebasedbranch import RefreshRegistryRebasedBranch
@@ -11,6 +14,8 @@ from .models import InfrahubEvent
11
14
  class BranchDeletedEvent(InfrahubEvent):
12
15
  """Event generated when a branch has been deleted"""
13
16
 
17
+ event_name: ClassVar[str] = f"{EVENT_NAMESPACE}.branch.deleted"
18
+
14
19
  branch_name: str = Field(..., description="The name of the branch")
15
20
  branch_id: str = Field(..., description="The ID of the mutated node")
16
21
  sync_with_git: bool = Field(..., description="Indicates if the branch was extended to Git")
@@ -34,14 +39,12 @@ class BranchDeletedEvent(InfrahubEvent):
34
39
  ]
35
40
  return events
36
41
 
37
- @computed_field
38
- def event_name(self) -> str:
39
- return f"{EVENT_NAMESPACE}.branch.deleted"
40
-
41
42
 
42
43
  class BranchCreatedEvent(InfrahubEvent):
43
44
  """Event generated when a branch has been created"""
44
45
 
46
+ event_name: ClassVar[str] = f"{EVENT_NAMESPACE}.branch.created"
47
+
45
48
  branch_name: str = Field(..., description="The name of the branch")
46
49
  branch_id: str = Field(..., description="The ID of the branch")
47
50
  sync_with_git: bool = Field(..., description="Indicates if the branch was extended to Git")
@@ -65,33 +68,44 @@ class BranchCreatedEvent(InfrahubEvent):
65
68
  ]
66
69
  return events
67
70
 
68
- @computed_field
69
- def event_name(self) -> str:
70
- return f"{EVENT_NAMESPACE}.branch.created"
71
-
72
71
 
73
72
  class BranchMergedEvent(InfrahubEvent):
74
73
  """Event generated when a branch has been merged"""
75
74
 
75
+ event_name: ClassVar[str] = f"{EVENT_NAMESPACE}.branch.merged"
76
+
77
+ branch_name: str = Field(..., description="The name of the branch")
78
+ branch_id: str = Field(..., description="The ID of the branch")
79
+ proposed_change_id: str | None = Field(
80
+ default=None, description="The ID of the proposed change that merged this branch if applicable"
81
+ )
82
+
76
83
  def get_resource(self) -> dict[str, str]:
77
84
  return {
78
- "prefect.resource.id": f"infrahub.branch.{self.meta.get_branch_id()}",
79
- "infrahub.node.kind": "Branch",
80
- "infrahub.node.id": self.meta.get_branch_id(),
81
- "infrahub.node.label": self.meta.context.branch.name,
85
+ "prefect.resource.id": f"infrahub.branch.{self.branch_name}",
86
+ "infrahub.branch.id": self.branch_id,
87
+ "infrahub.branch.name": self.branch_name,
82
88
  }
83
89
 
84
- def get_messages(self) -> list[InfrahubMessage]:
85
- return []
90
+ def get_related(self) -> list[dict[str, str]]:
91
+ related = super().get_related()
92
+ if self.proposed_change_id:
93
+ related.append(
94
+ {
95
+ "prefect.resource.id": self.proposed_change_id,
96
+ "prefect.resource.role": "infrahub.related.node",
97
+ "infrahub.node.kind": InfrahubKind.PROPOSEDCHANGE,
98
+ }
99
+ )
86
100
 
87
- @computed_field
88
- def event_name(self) -> str:
89
- return f"{EVENT_NAMESPACE}.branch.merged"
101
+ return related
90
102
 
91
103
 
92
104
  class BranchRebasedEvent(InfrahubEvent):
93
105
  """Event generated when a branch has been rebased"""
94
106
 
107
+ event_name: ClassVar[str] = f"{EVENT_NAMESPACE}.branch.rebased"
108
+
95
109
  branch_id: str = Field(..., description="The ID of the mutated node")
96
110
  branch_name: str = Field(..., description="The name of the branch")
97
111
 
@@ -99,6 +113,7 @@ class BranchRebasedEvent(InfrahubEvent):
99
113
  return {
100
114
  "prefect.resource.id": f"infrahub.branch.{self.branch_name}",
101
115
  "infrahub.branch.id": self.branch_id,
116
+ "infrahub.branch.name": self.branch_name,
102
117
  }
103
118
 
104
119
  def get_messages(self) -> list[InfrahubMessage]:
@@ -110,7 +125,3 @@ class BranchRebasedEvent(InfrahubEvent):
110
125
  RefreshRegistryRebasedBranch(branch=self.branch_name),
111
126
  ]
112
127
  return events
113
-
114
- @computed_field
115
- def event_name(self) -> str:
116
- return f"{EVENT_NAMESPACE}.branch.rebased"
@@ -0,0 +1,71 @@
1
+ from infrahub.context import InfrahubContext
2
+ from infrahub.core.branch import Branch
3
+ from infrahub.core.changelog.models import RelationshipChangelogGetter
4
+ from infrahub.core.constants import MutationAction
5
+ from infrahub.core.node import Node
6
+ from infrahub.database import InfrahubDatabase
7
+ from infrahub.events.node_action import NodeDeletedEvent, NodeMutatedEvent, NodeUpdatedEvent, get_node_event
8
+ from infrahub.groups.parsers import GroupNodeMutationParser
9
+ from infrahub.worker import WORKER_IDENTITY
10
+
11
+ from .models import EventMeta, InfrahubEvent
12
+
13
+
14
+ async def generate_node_mutation_events(
15
+ node: Node,
16
+ deleted_nodes: list[Node],
17
+ db: InfrahubDatabase,
18
+ branch: Branch,
19
+ context: InfrahubContext,
20
+ request_id: str,
21
+ action: MutationAction,
22
+ ) -> list[InfrahubEvent]:
23
+ meta = EventMeta(
24
+ account_id=context.account.account_id,
25
+ initiator_id=WORKER_IDENTITY,
26
+ request_id=request_id,
27
+ branch=branch,
28
+ context=context,
29
+ )
30
+ node_event_class = get_node_event(action)
31
+ main_event = node_event_class(
32
+ kind=node.get_kind(),
33
+ node_id=node.id,
34
+ changelog=node.node_changelog,
35
+ fields=node.node_changelog.updated_fields,
36
+ meta=meta,
37
+ )
38
+ relationship_changelogs = RelationshipChangelogGetter(db=db, branch=branch)
39
+ node_changelogs = await relationship_changelogs.get_changelogs(primary_changelog=node.node_changelog)
40
+
41
+ events: list[NodeMutatedEvent] = [main_event]
42
+
43
+ deleted_changelogs = [deleted_node.node_changelog for deleted_node in deleted_nodes if deleted_node.id != node.id]
44
+ deleted_ids = {deleted_node.node_id for deleted_node in deleted_changelogs}
45
+
46
+ for node_changelog in deleted_changelogs:
47
+ meta = EventMeta.from_parent(parent=main_event)
48
+ delete_event = NodeDeletedEvent(
49
+ kind=node_changelog.node_kind,
50
+ node_id=node_changelog.node_id,
51
+ changelog=node_changelog,
52
+ fields=node_changelog.updated_fields,
53
+ meta=meta,
54
+ )
55
+ events.append(delete_event)
56
+
57
+ for node_changelog in node_changelogs:
58
+ if node_changelog.node_id not in deleted_ids:
59
+ meta = EventMeta.from_parent(parent=main_event)
60
+ update_event = NodeUpdatedEvent(
61
+ kind=node_changelog.node_kind,
62
+ node_id=node_changelog.node_id,
63
+ changelog=node_changelog,
64
+ fields=node_changelog.updated_fields,
65
+ meta=meta,
66
+ )
67
+ events.append(update_event)
68
+
69
+ group_parser = GroupNodeMutationParser(db=db, branch=branch)
70
+ group_events = await group_parser.group_events_from_node_actions(events=events)
71
+ return events + group_events
@@ -1,9 +1,8 @@
1
- from typing import Any
1
+ from typing import ClassVar
2
2
 
3
- from pydantic import Field, computed_field
3
+ from pydantic import Field
4
4
 
5
5
  from infrahub.core.constants import MutationAction
6
- from infrahub.message_bus import InfrahubMessage
7
6
 
8
7
  from .constants import EVENT_NAMESPACE
9
8
  from .models import EventNode, InfrahubEvent
@@ -16,6 +15,9 @@ class GroupMutatedEvent(InfrahubEvent):
16
15
  node_id: str = Field(..., description="The ID of the updated group")
17
16
  action: MutationAction = Field(..., description="The action taken on the node")
18
17
  members: list[EventNode] = Field(default_factory=list, description="Updated members during this event.")
18
+ ancestors: list[EventNode] = Field(
19
+ default_factory=list, description="A list of groups that are ancestors of this group."
20
+ )
19
21
 
20
22
  def get_related(self) -> list[dict[str, str]]:
21
23
  related = super().get_related()
@@ -26,7 +28,22 @@ class GroupMutatedEvent(InfrahubEvent):
26
28
  "infrahub.node.kind": self.kind,
27
29
  }
28
30
  )
31
+ related.append(
32
+ {
33
+ "prefect.resource.id": self.node_id,
34
+ "prefect.resource.role": "infrahub.group.update",
35
+ "infrahub.node.kind": self.kind,
36
+ }
37
+ )
38
+
29
39
  for member in self.members:
40
+ related.append(
41
+ {
42
+ "prefect.resource.id": member.id,
43
+ "prefect.resource.role": "infrahub.group.member",
44
+ "infrahub.node.kind": member.kind,
45
+ }
46
+ )
30
47
  related.append(
31
48
  {
32
49
  "prefect.resource.id": member.id,
@@ -35,11 +52,30 @@ class GroupMutatedEvent(InfrahubEvent):
35
52
  }
36
53
  )
37
54
 
38
- return related
55
+ for ancestor in self.ancestors:
56
+ related.append(
57
+ {
58
+ "prefect.resource.id": ancestor.id,
59
+ "prefect.resource.role": "infrahub.group.ancestor",
60
+ "infrahub.node.kind": ancestor.kind,
61
+ }
62
+ )
63
+ related.append(
64
+ {
65
+ "prefect.resource.id": ancestor.id,
66
+ "prefect.resource.role": "infrahub.related.node",
67
+ "infrahub.node.kind": ancestor.kind,
68
+ }
69
+ )
70
+ related.append(
71
+ {
72
+ "prefect.resource.id": ancestor.id,
73
+ "prefect.resource.role": "infrahub.group.update",
74
+ "infrahub.node.kind": ancestor.kind,
75
+ }
76
+ )
39
77
 
40
- @computed_field
41
- def event_name(self) -> str:
42
- return f"{EVENT_NAMESPACE}.group.{self.action.value}"
78
+ return related
43
79
 
44
80
  def get_resource(self) -> dict[str, str]:
45
81
  return {
@@ -50,24 +86,18 @@ class GroupMutatedEvent(InfrahubEvent):
50
86
  "infrahub.node.root_id": self.node_id,
51
87
  }
52
88
 
53
- def get_payload(self) -> dict[str, Any]:
54
- return {"members": [member.model_dump() for member in self.members]}
55
-
56
- def get_messages(self) -> list[InfrahubMessage]:
57
- return []
58
-
59
89
 
60
90
  class GroupMemberAddedEvent(GroupMutatedEvent):
61
- action: MutationAction = MutationAction.CREATED
91
+ """Event generated when a one or more members have been added to a group"""
62
92
 
63
- @computed_field
64
- def event_name(self) -> str:
65
- return f"{EVENT_NAMESPACE}.group.member_added"
93
+ action: MutationAction = MutationAction.CREATED
94
+ event_name: ClassVar[str] = f"{EVENT_NAMESPACE}.group.member_added"
95
+ infrahub_node_kind_event: ClassVar[bool] = True
66
96
 
67
97
 
68
98
  class GroupMemberRemovedEvent(GroupMutatedEvent):
69
- action: MutationAction = MutationAction.DELETED
99
+ """Event generated when a one or more members have been removed to a group"""
70
100
 
71
- @computed_field
72
- def event_name(self) -> str:
73
- return f"{EVENT_NAMESPACE}.group.member_removed"
101
+ action: MutationAction = MutationAction.DELETED
102
+ event_name: ClassVar[str] = f"{EVENT_NAMESPACE}.group.member_removed"
103
+ infrahub_node_kind_event: ClassVar[bool] = True
infrahub/events/models.py CHANGED
@@ -1,10 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from copy import deepcopy
4
- from typing import Any, Self, cast, final
4
+ from typing import Any, ClassVar, Self, final
5
5
  from uuid import UUID, uuid4
6
6
 
7
- from pydantic import BaseModel, Field, PrivateAttr, computed_field, model_validator
7
+ from pydantic import BaseModel, Field, PrivateAttr, model_validator
8
8
 
9
9
  from infrahub import __version__
10
10
  from infrahub.auth import AccountSession, AuthType
@@ -27,7 +27,7 @@ class ParentEvent(BaseModel):
27
27
 
28
28
 
29
29
  class EventMeta(BaseModel):
30
- branch: Branch | None = Field(default=None)
30
+ branch: Branch | None = Field(default=None, description="The branch on which originate this event")
31
31
  request_id: str = ""
32
32
  account_id: str | None = Field(default=None, description="The ID of the account triggering this event")
33
33
  initiator_id: str = Field(
@@ -112,12 +112,17 @@ class EventMeta(BaseModel):
112
112
  )
113
113
 
114
114
  @classmethod
115
- def from_parent(cls, parent: InfrahubEvent) -> EventMeta:
115
+ def from_parent(cls, parent: InfrahubEvent, branch: Branch | None = None) -> EventMeta:
116
116
  """Create the metadata from an existing event
117
117
 
118
118
  Note that this action will modify the existing event to indicate that children might be attached to the event
119
119
  """
120
120
  parent.meta.has_children = True
121
+ context = deepcopy(parent.meta.context)
122
+ if branch:
123
+ context.branch.name = branch.name
124
+ context.branch.id = str(branch.get_uuid())
125
+
121
126
  return cls(
122
127
  parent=parent.meta.id,
123
128
  branch=parent.meta.branch,
@@ -125,8 +130,8 @@ class EventMeta(BaseModel):
125
130
  initiator_id=parent.meta.initiator_id,
126
131
  account_id=parent.meta.account_id,
127
132
  level=parent.meta.level + 1,
128
- context=deepcopy(parent.meta.context),
129
- ancestors=[ParentEvent(id=parent.get_id(), name=parent.get_name())] + parent.meta.ancestors,
133
+ context=context,
134
+ ancestors=[ParentEvent(id=parent.get_id(), name=parent.event_name)] + parent.meta.ancestors,
130
135
  )
131
136
 
132
137
  @classmethod
@@ -143,21 +148,20 @@ class EventMeta(BaseModel):
143
148
  class InfrahubEvent(BaseModel):
144
149
  meta: EventMeta = Field(..., description="Metadata for the event")
145
150
 
151
+ event_name: ClassVar[str] = Field(..., description="The name of the event")
152
+ infrahub_node_kind_event: ClassVar[bool] = False
153
+
146
154
  def get_id(self) -> str:
147
155
  return self.meta.get_id()
148
156
 
149
157
  def get_event_namespace(self) -> str:
150
158
  return EVENT_NAMESPACE
151
159
 
152
- def get_name(self) -> str:
153
- # Convince linters that @computed_field is a property and not a method...
154
- return cast(str, self.event_name)
155
-
156
160
  def get_resource(self) -> dict[str, str]:
157
161
  raise NotImplementedError
158
162
 
159
163
  def get_messages(self) -> list[InfrahubMessage]:
160
- raise NotImplementedError
164
+ return []
161
165
 
162
166
  def get_related(self) -> list[dict[str, str]]:
163
167
  if not self.meta:
@@ -171,13 +175,12 @@ class InfrahubEvent(BaseModel):
171
175
  be used for that as it will always contain the 'context' key regardless of changes
172
176
  in child classes
173
177
  """
174
- return {}
178
+ return self.model_dump(exclude={"meta"})
175
179
 
176
180
  @final
177
181
  def get_event_payload(self) -> dict[str, Any]:
178
182
  """This method should be used when emitting the event to the event broker"""
179
- event_payload = self.get_payload()
180
- event_payload["context"] = self.meta.context.model_dump(mode="json")
183
+ event_payload = {"data": self.get_payload(), "context": self.meta.context.to_event()}
181
184
  return event_payload
182
185
 
183
186
  def get_message_meta(self) -> Meta:
@@ -189,13 +192,9 @@ class InfrahubEvent(BaseModel):
189
192
 
190
193
  return meta
191
194
 
192
- @computed_field
193
- def event_name(self) -> str:
194
- raise NotImplementedError("The event name has not been defined")
195
-
196
195
  @model_validator(mode="after")
197
196
  def update_context(self) -> Self:
198
197
  """Update the context object using this event provided that the meta data was created with a context."""
199
198
  if self.meta._created_with_context:
200
- self.meta.context.set_event(self.get_name(), id=self.get_id())
199
+ self.meta.context.set_event(self.event_name, id=self.get_id())
201
200
  return self