infrahub-server 1.1.6__py3-none-any.whl → 1.2.0rc0__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 (346) hide show
  1. infrahub/api/artifact.py +16 -4
  2. infrahub/api/dependencies.py +8 -0
  3. infrahub/api/oauth2.py +0 -1
  4. infrahub/api/oidc.py +0 -1
  5. infrahub/api/query.py +18 -7
  6. infrahub/api/schema.py +32 -6
  7. infrahub/api/transformation.py +12 -5
  8. infrahub/{message_bus/messages/check_artifact_create.py → artifacts/models.py} +2 -4
  9. infrahub/{message_bus/operations/check/artifact.py → artifacts/tasks.py} +26 -25
  10. infrahub/cli/__init__.py +0 -2
  11. infrahub/cli/db.py +6 -7
  12. infrahub/cli/events.py +8 -3
  13. infrahub/cli/git_agent.py +9 -7
  14. infrahub/cli/tasks.py +4 -6
  15. infrahub/computed_attribute/tasks.py +63 -17
  16. infrahub/computed_attribute/triggers.py +90 -0
  17. infrahub/config.py +1 -1
  18. infrahub/context.py +39 -0
  19. infrahub/core/account.py +5 -8
  20. infrahub/core/attribute.py +53 -21
  21. infrahub/core/branch/models.py +4 -4
  22. infrahub/core/branch/tasks.py +89 -130
  23. infrahub/core/changelog/__init__.py +0 -0
  24. infrahub/core/changelog/diff.py +232 -0
  25. infrahub/core/changelog/models.py +488 -0
  26. infrahub/core/constants/__init__.py +19 -2
  27. infrahub/core/constants/infrahubkind.py +1 -0
  28. infrahub/core/diff/combiner.py +12 -8
  29. infrahub/core/diff/coordinator.py +49 -70
  30. infrahub/core/diff/data_check_synchronizer.py +86 -7
  31. infrahub/core/diff/enricher/aggregated.py +3 -3
  32. infrahub/core/diff/enricher/cardinality_one.py +2 -7
  33. infrahub/core/diff/enricher/hierarchy.py +5 -3
  34. infrahub/core/diff/enricher/labels.py +14 -4
  35. infrahub/core/diff/enricher/path_identifier.py +3 -9
  36. infrahub/core/diff/enricher/summary_counts.py +3 -1
  37. infrahub/core/diff/merger/merger.py +8 -4
  38. infrahub/core/diff/model/path.py +47 -29
  39. infrahub/core/diff/query/all_conflicts.py +6 -3
  40. infrahub/core/diff/query/artifact.py +1 -1
  41. infrahub/core/diff/query/delete_query.py +1 -1
  42. infrahub/core/diff/query/diff_get.py +3 -2
  43. infrahub/core/diff/query/diff_summary.py +1 -1
  44. infrahub/core/diff/query/field_specifiers.py +3 -1
  45. infrahub/core/diff/query/field_summary.py +3 -2
  46. infrahub/core/diff/query/filters.py +12 -1
  47. infrahub/core/diff/query/get_conflict_query.py +1 -1
  48. infrahub/core/diff/query/has_conflicts_query.py +6 -3
  49. infrahub/core/diff/query/merge.py +3 -3
  50. infrahub/core/diff/query/{drop_tracking_id.py → merge_tracking_id.py} +4 -4
  51. infrahub/core/diff/query/roots_metadata.py +9 -2
  52. infrahub/core/diff/query/save.py +151 -66
  53. infrahub/core/diff/query/summary_counts_enricher.py +220 -0
  54. infrahub/core/diff/query/time_range_query.py +3 -2
  55. infrahub/core/diff/query/update_conflict_query.py +1 -1
  56. infrahub/core/diff/query_parser.py +49 -24
  57. infrahub/core/diff/repository/deserializer.py +24 -25
  58. infrahub/core/diff/repository/repository.py +76 -20
  59. infrahub/core/diff/tasks.py +9 -8
  60. infrahub/core/enums.py +1 -1
  61. infrahub/core/integrity/object_conflict/conflict_recorder.py +1 -1
  62. infrahub/core/ipam/reconciler.py +1 -1
  63. infrahub/core/ipam/tasks.py +2 -3
  64. infrahub/core/manager.py +18 -13
  65. infrahub/core/merge.py +5 -2
  66. infrahub/core/migrations/graph/m001_add_version_to_graph.py +1 -1
  67. infrahub/core/migrations/graph/m002_attribute_is_default.py +2 -2
  68. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +2 -2
  69. infrahub/core/migrations/graph/m004_add_attr_documentation.py +1 -1
  70. infrahub/core/migrations/graph/m005_add_rel_read_only.py +1 -1
  71. infrahub/core/migrations/graph/m006_add_rel_on_delete.py +1 -1
  72. infrahub/core/migrations/graph/m007_add_rel_allow_override.py +1 -1
  73. infrahub/core/migrations/graph/m008_add_human_friendly_id.py +1 -1
  74. infrahub/core/migrations/graph/m009_add_generate_profile_attr.py +1 -1
  75. infrahub/core/migrations/graph/m010_add_generate_profile_attr_generic.py +1 -1
  76. infrahub/core/migrations/graph/m011_remove_profile_relationship_schema.py +2 -2
  77. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -23
  78. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -11
  79. infrahub/core/migrations/graph/m014_remove_index_attr_value.py +2 -2
  80. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
  81. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
  82. infrahub/core/migrations/graph/m017_add_core_profile.py +1 -1
  83. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -2
  84. infrahub/core/migrations/query/attribute_add.py +1 -1
  85. infrahub/core/migrations/query/attribute_rename.py +1 -1
  86. infrahub/core/migrations/query/delete_element_in_schema.py +1 -1
  87. infrahub/core/migrations/query/node_duplicate.py +1 -1
  88. infrahub/core/migrations/query/relationship_duplicate.py +1 -1
  89. infrahub/core/migrations/query/schema_attribute_update.py +1 -1
  90. infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
  91. infrahub/core/migrations/schema/node_remove.py +1 -1
  92. infrahub/core/migrations/schema/tasks.py +5 -5
  93. infrahub/core/migrations/shared.py +4 -4
  94. infrahub/core/models.py +7 -8
  95. infrahub/core/node/__init__.py +161 -40
  96. infrahub/core/node/base.py +1 -1
  97. infrahub/core/node/constraints/grouped_uniqueness.py +9 -2
  98. infrahub/core/node/delete_validator.py +4 -4
  99. infrahub/core/node/ipam.py +13 -8
  100. infrahub/core/node/permissions.py +4 -0
  101. infrahub/core/node/resource_manager/ip_prefix_pool.py +8 -5
  102. infrahub/core/node/standard.py +3 -5
  103. infrahub/core/property.py +1 -1
  104. infrahub/core/protocols.py +4 -0
  105. infrahub/core/protocols_base.py +4 -2
  106. infrahub/core/query/__init__.py +2 -5
  107. infrahub/core/query/attribute.py +9 -9
  108. infrahub/core/query/branch.py +5 -5
  109. infrahub/core/query/delete.py +1 -1
  110. infrahub/core/query/diff.py +45 -7
  111. infrahub/core/query/ipam.py +4 -4
  112. infrahub/core/query/node.py +19 -14
  113. infrahub/core/query/relationship.py +10 -11
  114. infrahub/core/query/resource_manager.py +13 -11
  115. infrahub/core/query/standard_node.py +6 -6
  116. infrahub/core/query/task.py +3 -3
  117. infrahub/core/query/task_log.py +1 -1
  118. infrahub/core/query/utils.py +5 -5
  119. infrahub/core/registry.py +0 -2
  120. infrahub/core/relationship/constraints/count.py +1 -1
  121. infrahub/core/relationship/constraints/peer_kind.py +1 -1
  122. infrahub/core/relationship/model.py +66 -26
  123. infrahub/core/schema/__init__.py +6 -4
  124. infrahub/core/schema/basenode_schema.py +1 -3
  125. infrahub/core/schema/definitions/core.py +14 -2
  126. infrahub/core/schema/definitions/internal.py +16 -0
  127. infrahub/core/schema/generated/genericnode_schema.py +5 -0
  128. infrahub/core/schema/generated/node_schema.py +5 -0
  129. infrahub/core/schema/generic_schema.py +5 -1
  130. infrahub/core/schema/manager.py +45 -42
  131. infrahub/core/schema/node_schema.py +4 -0
  132. infrahub/core/schema/profile_schema.py +4 -0
  133. infrahub/core/schema/relationship_schema.py +2 -2
  134. infrahub/core/schema/schema_branch.py +248 -14
  135. infrahub/core/schema/template_schema.py +36 -0
  136. infrahub/core/task/user_task.py +7 -5
  137. infrahub/core/timestamp.py +1 -1
  138. infrahub/core/utils.py +3 -2
  139. infrahub/core/validators/attribute/choices.py +1 -1
  140. infrahub/core/validators/attribute/enum.py +1 -1
  141. infrahub/core/validators/attribute/kind.py +1 -1
  142. infrahub/core/validators/attribute/length.py +1 -1
  143. infrahub/core/validators/attribute/optional.py +1 -1
  144. infrahub/core/validators/attribute/regex.py +1 -1
  145. infrahub/core/validators/attribute/unique.py +1 -1
  146. infrahub/core/validators/checks_runner.py +37 -0
  147. infrahub/core/validators/node/generate_profile.py +1 -1
  148. infrahub/core/validators/node/hierarchy.py +1 -1
  149. infrahub/core/validators/query.py +1 -1
  150. infrahub/core/validators/relationship/count.py +1 -1
  151. infrahub/core/validators/relationship/optional.py +1 -1
  152. infrahub/core/validators/relationship/peer.py +1 -1
  153. infrahub/core/validators/tasks.py +8 -6
  154. infrahub/core/validators/uniqueness/query.py +20 -17
  155. infrahub/database/__init__.py +15 -2
  156. infrahub/database/memgraph.py +1 -1
  157. infrahub/dependencies/builder/constraint/grouped/node_runner.py +0 -2
  158. infrahub/dependencies/builder/diff/combiner.py +1 -1
  159. infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
  160. infrahub/dependencies/builder/diff/coordinator.py +0 -2
  161. infrahub/dependencies/builder/diff/deserializer.py +1 -1
  162. infrahub/dependencies/builder/diff/enricher/summary_counts.py +1 -1
  163. infrahub/events/branch_action.py +47 -21
  164. infrahub/events/group_action.py +73 -0
  165. infrahub/events/models.py +159 -51
  166. infrahub/events/node_action.py +74 -8
  167. infrahub/events/repository_action.py +8 -8
  168. infrahub/events/schema_action.py +21 -8
  169. infrahub/generators/tasks.py +12 -13
  170. infrahub/git/base.py +3 -5
  171. infrahub/git/constants.py +0 -1
  172. infrahub/git/integrator.py +36 -35
  173. infrahub/git/repository.py +7 -8
  174. infrahub/git/tasks.py +43 -107
  175. infrahub/git_credential/helper.py +2 -3
  176. infrahub/graphql/analyzer.py +572 -11
  177. infrahub/graphql/app.py +34 -26
  178. infrahub/graphql/auth/query_permission_checker/anonymous_checker.py +5 -5
  179. infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +4 -4
  180. infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +4 -4
  181. infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +28 -35
  182. infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -5
  183. infrahub/graphql/enums.py +1 -1
  184. infrahub/graphql/initialization.py +5 -1
  185. infrahub/graphql/loaders/node.py +2 -2
  186. infrahub/graphql/manager.py +59 -54
  187. infrahub/graphql/mutations/account.py +20 -13
  188. infrahub/graphql/mutations/artifact_definition.py +16 -12
  189. infrahub/graphql/mutations/branch.py +61 -40
  190. infrahub/graphql/mutations/computed_attribute.py +19 -13
  191. infrahub/graphql/mutations/diff.py +37 -9
  192. infrahub/graphql/mutations/diff_conflict.py +9 -8
  193. infrahub/graphql/mutations/graphql_query.py +19 -11
  194. infrahub/graphql/mutations/ipam.py +21 -19
  195. infrahub/graphql/mutations/main.py +197 -44
  196. infrahub/graphql/mutations/menu.py +8 -8
  197. infrahub/graphql/mutations/proposed_change.py +36 -28
  198. infrahub/graphql/mutations/relationship.py +302 -105
  199. infrahub/graphql/mutations/repository.py +41 -35
  200. infrahub/graphql/mutations/resource_manager.py +26 -26
  201. infrahub/graphql/mutations/schema.py +51 -33
  202. infrahub/graphql/mutations/tasks.py +16 -10
  203. infrahub/graphql/parser.py +1 -1
  204. infrahub/graphql/permissions.py +6 -4
  205. infrahub/graphql/queries/account.py +22 -18
  206. infrahub/graphql/queries/branch.py +6 -4
  207. infrahub/graphql/queries/diff/tree.py +48 -42
  208. infrahub/graphql/queries/event.py +112 -0
  209. infrahub/graphql/queries/internal.py +3 -3
  210. infrahub/graphql/queries/ipam.py +23 -18
  211. infrahub/graphql/queries/relationship.py +11 -10
  212. infrahub/graphql/queries/resource_manager.py +43 -27
  213. infrahub/graphql/queries/search.py +9 -8
  214. infrahub/graphql/queries/status.py +12 -9
  215. infrahub/graphql/queries/task.py +11 -9
  216. infrahub/graphql/resolvers/resolver.py +69 -43
  217. infrahub/graphql/resolvers/single_relationship.py +16 -10
  218. infrahub/graphql/schema.py +2 -0
  219. infrahub/graphql/subscription/__init__.py +1 -1
  220. infrahub/graphql/subscription/events.py +1 -1
  221. infrahub/graphql/subscription/graphql_query.py +8 -8
  222. infrahub/graphql/types/branch.py +2 -2
  223. infrahub/graphql/types/common.py +6 -1
  224. infrahub/graphql/types/enums.py +2 -0
  225. infrahub/graphql/types/event.py +100 -0
  226. infrahub/graphql/types/interface.py +2 -2
  227. infrahub/graphql/types/node.py +3 -3
  228. infrahub/graphql/types/permission.py +2 -2
  229. infrahub/graphql/types/relationship.py +3 -3
  230. infrahub/graphql/types/standard_node.py +9 -11
  231. infrahub/graphql/utils.py +28 -182
  232. infrahub/groups/tasks.py +2 -3
  233. infrahub/lock.py +1 -1
  234. infrahub/menu/constants.py +1 -0
  235. infrahub/menu/generator.py +14 -3
  236. infrahub/menu/menu.py +116 -127
  237. infrahub/menu/models.py +4 -4
  238. infrahub/message_bus/messages/__init__.py +0 -4
  239. infrahub/message_bus/messages/event_branch_merge.py +3 -0
  240. infrahub/message_bus/messages/request_proposedchange_pipeline.py +2 -0
  241. infrahub/message_bus/operations/__init__.py +3 -5
  242. infrahub/message_bus/operations/check/__init__.py +2 -2
  243. infrahub/message_bus/operations/check/generator.py +1 -3
  244. infrahub/message_bus/operations/check/repository.py +1 -1
  245. infrahub/message_bus/operations/event/branch.py +7 -3
  246. infrahub/message_bus/operations/event/schema.py +1 -1
  247. infrahub/message_bus/operations/finalize/validator.py +1 -1
  248. infrahub/message_bus/operations/git/file.py +2 -2
  249. infrahub/message_bus/operations/git/repository.py +1 -1
  250. infrahub/message_bus/operations/requests/__init__.py +0 -2
  251. infrahub/message_bus/operations/requests/generator_definition.py +1 -1
  252. infrahub/message_bus/operations/requests/proposed_change.py +26 -11
  253. infrahub/message_bus/operations/requests/repository.py +2 -2
  254. infrahub/message_bus/operations/send/echo.py +1 -1
  255. infrahub/message_bus/types.py +1 -1
  256. infrahub/permissions/__init__.py +2 -1
  257. infrahub/permissions/types.py +26 -0
  258. infrahub/pools/prefix.py +29 -165
  259. infrahub/prefect_server/__init__.py +0 -0
  260. infrahub/prefect_server/app.py +18 -0
  261. infrahub/prefect_server/database.py +20 -0
  262. infrahub/prefect_server/events.py +28 -0
  263. infrahub/prefect_server/models.py +46 -0
  264. infrahub/proposed_change/models.py +15 -1
  265. infrahub/proposed_change/tasks.py +173 -35
  266. infrahub/pytest_plugin.py +4 -4
  267. infrahub/server.py +12 -11
  268. infrahub/services/__init__.py +147 -62
  269. infrahub/services/adapters/cache/__init__.py +7 -5
  270. infrahub/services/adapters/cache/nats.py +40 -22
  271. infrahub/services/adapters/cache/redis.py +0 -4
  272. infrahub/services/adapters/event/__init__.py +10 -18
  273. infrahub/services/adapters/http/__init__.py +0 -5
  274. infrahub/services/adapters/http/httpx.py +22 -15
  275. infrahub/services/adapters/message_bus/__init__.py +23 -6
  276. infrahub/services/adapters/message_bus/local.py +8 -6
  277. infrahub/services/adapters/message_bus/nats.py +12 -6
  278. infrahub/services/adapters/message_bus/rabbitmq.py +22 -9
  279. infrahub/services/adapters/workflow/__init__.py +11 -8
  280. infrahub/services/adapters/workflow/local.py +28 -7
  281. infrahub/services/adapters/workflow/worker.py +23 -7
  282. infrahub/services/component.py +38 -35
  283. infrahub/services/scheduler.py +32 -29
  284. infrahub/storage.py +2 -4
  285. infrahub/task_manager/constants.py +1 -1
  286. infrahub/task_manager/event.py +182 -0
  287. infrahub/task_manager/models.py +125 -1
  288. infrahub/task_manager/task.py +1 -1
  289. infrahub/tasks/artifact.py +14 -16
  290. infrahub/tasks/registry.py +1 -1
  291. infrahub/tasks/telemetry.py +13 -14
  292. infrahub/transformations/tasks.py +3 -5
  293. infrahub/trigger/__init__.py +0 -0
  294. infrahub/trigger/catalogue.py +15 -0
  295. infrahub/trigger/constants.py +9 -0
  296. infrahub/trigger/models.py +69 -0
  297. infrahub/trigger/tasks.py +85 -0
  298. infrahub/types.py +1 -1
  299. infrahub/utils.py +1 -1
  300. infrahub/webhook/constants.py +0 -2
  301. infrahub/webhook/models.py +8 -2
  302. infrahub/webhook/tasks.py +20 -73
  303. infrahub/webhook/triggers.py +20 -0
  304. infrahub/workers/infrahub_async.py +36 -25
  305. infrahub/workers/utils.py +63 -0
  306. infrahub/workflows/catalogue.py +13 -37
  307. infrahub/workflows/initialization.py +6 -8
  308. infrahub/workflows/models.py +3 -5
  309. infrahub/workflows/utils.py +1 -1
  310. infrahub_sdk/ctl/check.py +3 -3
  311. infrahub_sdk/ctl/cli_commands.py +11 -10
  312. infrahub_sdk/ctl/exceptions.py +0 -6
  313. infrahub_sdk/ctl/exporter.py +1 -1
  314. infrahub_sdk/ctl/generator.py +5 -5
  315. infrahub_sdk/ctl/importer.py +3 -2
  316. infrahub_sdk/ctl/menu.py +1 -1
  317. infrahub_sdk/ctl/object.py +1 -1
  318. infrahub_sdk/ctl/repository.py +23 -15
  319. infrahub_sdk/ctl/schema.py +2 -2
  320. infrahub_sdk/ctl/utils.py +4 -3
  321. infrahub_sdk/ctl/validate.py +2 -1
  322. infrahub_sdk/exceptions.py +6 -0
  323. infrahub_sdk/generator.py +3 -0
  324. infrahub_sdk/node.py +2 -2
  325. infrahub_sdk/schema/__init__.py +14 -2
  326. infrahub_sdk/schema/main.py +7 -0
  327. infrahub_sdk/utils.py +11 -1
  328. infrahub_sdk/yaml.py +2 -3
  329. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/METADATA +46 -12
  330. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/RECORD +338 -321
  331. infrahub_testcontainers/container.py +14 -6
  332. infrahub_testcontainers/docker-compose.test.yml +24 -5
  333. infrahub_testcontainers/haproxy.cfg +43 -0
  334. infrahub_testcontainers/helpers.py +85 -1
  335. infrahub/core/branch/constants.py +0 -2
  336. infrahub/graphql/query.py +0 -52
  337. infrahub/message_bus/messages/request_artifactdefinition_check.py +0 -17
  338. infrahub/message_bus/operations/requests/artifact_definition.py +0 -148
  339. infrahub/schema/constants.py +0 -1
  340. infrahub/schema/tasks.py +0 -76
  341. infrahub/services/adapters/database/__init__.py +0 -9
  342. infrahub_sdk/ctl/_file.py +0 -13
  343. /infrahub/{schema → artifacts}/__init__.py +0 -0
  344. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/LICENSE.txt +0 -0
  345. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/WHEEL +0 -0
  346. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/entry_points.txt +0 -0
@@ -1,50 +1,168 @@
1
- from typing import Awaitable, Callable, Optional
1
+ from __future__ import annotations
2
2
 
3
- from infrahub_sdk import InfrahubClient
3
+ from typing import TYPE_CHECKING, Awaitable, Callable, Optional
4
4
 
5
5
  from infrahub.components import ComponentType
6
- from infrahub.database import InfrahubDatabase
7
6
  from infrahub.exceptions import InitializationError
8
7
  from infrahub.log import get_logger
9
- from infrahub.message_bus import InfrahubMessage, InfrahubResponse
10
8
  from infrahub.message_bus.messages import ROUTING_KEY_MAP
11
- from infrahub.message_bus.types import MessageTTL
12
9
 
13
- from .adapters.cache import InfrahubCache
14
10
  from .adapters.event import InfrahubEventService
15
- from .adapters.http import InfrahubHTTP
16
11
  from .adapters.http.httpx import HttpxAdapter
17
- from .adapters.message_bus import InfrahubMessageBus
18
- from .adapters.workflow import InfrahubWorkflow
12
+ from .adapters.workflow.local import WorkflowLocalExecution
13
+ from .adapters.workflow.worker import WorkflowWorkerExecution
19
14
  from .component import InfrahubComponent
20
- from .protocols import InfrahubLogger
21
15
  from .scheduler import InfrahubScheduler
22
16
 
17
+ if TYPE_CHECKING:
18
+ from infrahub_sdk import InfrahubClient
19
+
20
+ from infrahub.database import InfrahubDatabase
21
+ from infrahub.message_bus import InfrahubMessage
22
+ from infrahub.message_bus.types import MessageTTL
23
+
24
+ from .adapters.cache import InfrahubCache
25
+ from .adapters.http import InfrahubHTTP
26
+ from .adapters.message_bus import InfrahubMessageBus
27
+ from .adapters.workflow import InfrahubWorkflow
28
+ from .protocols import InfrahubLogger
29
+
23
30
 
24
31
  class InfrahubServices:
32
+ _cache: InfrahubCache | None
33
+ _client: InfrahubClient | None
34
+ _database: InfrahubDatabase | None
35
+ _message_bus: InfrahubMessageBus | None
36
+ _workflow: InfrahubWorkflow | None
37
+ _component: InfrahubComponent | None
38
+
39
+ log: InfrahubLogger
40
+ component_type: ComponentType
41
+ http: InfrahubHTTP
42
+ event: InfrahubEventService
43
+ scheduler: InfrahubScheduler
44
+
25
45
  def __init__(
26
46
  self,
27
- cache: Optional[InfrahubCache] = None,
28
- client: Optional[InfrahubClient] = None,
29
- database: Optional[InfrahubDatabase] = None,
30
- message_bus: Optional[InfrahubMessageBus] = None,
31
- http: InfrahubHTTP | None = None,
32
- workflow: Optional[InfrahubWorkflow] = None,
33
- event: InfrahubEventService | None = None,
34
- log: Optional[InfrahubLogger] = None,
35
- component_type: Optional[ComponentType] = None,
36
- ) -> None:
37
- self.cache = cache or InfrahubCache()
47
+ log: InfrahubLogger,
48
+ component_type: ComponentType,
49
+ http: InfrahubHTTP,
50
+ event: InfrahubEventService,
51
+ scheduler: InfrahubScheduler,
52
+ cache: InfrahubCache | None = None,
53
+ client: InfrahubClient | None = None,
54
+ database: InfrahubDatabase | None = None,
55
+ message_bus: InfrahubMessageBus | None = None,
56
+ workflow: InfrahubWorkflow | None = None,
57
+ ):
58
+ """
59
+ This method should not be called directly, use `new` instead for a proper initialization.
60
+ """
61
+
62
+ self._cache = cache
38
63
  self._client = client
39
64
  self._database = database
40
- self.message_bus = message_bus or InfrahubMessageBus()
41
- self.workflow = workflow or InfrahubWorkflow()
42
- self.event = event or InfrahubEventService()
43
- self.log = log or get_logger()
44
- self.component_type = component_type or ComponentType.NONE
45
- self.http = http or HttpxAdapter()
46
- self.scheduler = InfrahubScheduler()
47
- self.component = InfrahubComponent()
65
+ self._message_bus = message_bus
66
+ self._workflow = workflow
67
+ self.log = log
68
+ self.component_type = component_type
69
+ self.http = http
70
+ self.event = event
71
+ self.scheduler = scheduler
72
+ self._component = None
73
+
74
+ @classmethod
75
+ async def new(
76
+ cls,
77
+ cache: InfrahubCache | None = None,
78
+ client: InfrahubClient | None = None,
79
+ database: InfrahubDatabase | None = None,
80
+ event: InfrahubEventService | None = None,
81
+ message_bus: InfrahubMessageBus | None = None,
82
+ workflow: InfrahubWorkflow | None = None,
83
+ log: InfrahubLogger | None = None,
84
+ component_type: ComponentType | None = None,
85
+ http: InfrahubHTTP | None = None,
86
+ ) -> InfrahubServices:
87
+ """
88
+ Instantiate InfrahubServices object, and finalize initializations of underlying services having a circular
89
+ dependency with InfrahubServices.
90
+ """
91
+
92
+ component_type = component_type or ComponentType.NONE
93
+
94
+ scheduler = InfrahubScheduler(component_type)
95
+ service = cls(
96
+ cache=cache,
97
+ client=client,
98
+ database=database,
99
+ message_bus=message_bus,
100
+ workflow=workflow,
101
+ log=log or get_logger(),
102
+ component_type=component_type,
103
+ scheduler=scheduler,
104
+ event=event or InfrahubEventService(message_bus),
105
+ http=http or HttpxAdapter(),
106
+ )
107
+
108
+ # This circular dependency could be removed if InfrahubScheduler only depends on what it needs.
109
+ scheduler.service = service
110
+
111
+ if message_bus is not None:
112
+ # Need circular dependency for injecting `service` within `execute_message`. This might be removed
113
+ # using proper dependency injections.
114
+ message_bus.service = service
115
+
116
+ if cache is not None and database is not None:
117
+ component = await InfrahubComponent.new(
118
+ cache=cache, component_type=component_type, db=database, message_bus=message_bus
119
+ )
120
+ # We need to post init `service._component` because InfrahubComponent.new relies on message_bus
121
+ # itself relying on service.
122
+ service._component = component
123
+
124
+ if workflow is not None:
125
+ if isinstance(workflow, WorkflowWorkerExecution):
126
+ assert service.component is not None
127
+ # Ideally `WorkflowWorkerExecution.initialize` would be directly part of WorkflowWorkerExecution
128
+ # constructor but this requires some redesign as it depends on InfrahubComponent which is instantiated
129
+ # after workflow instantiation.
130
+ await workflow.initialize(
131
+ component_is_primary_server=await service.component.is_primary_gunicorn_worker()
132
+ )
133
+ elif isinstance(workflow, WorkflowLocalExecution):
134
+ # Circular dependency is only needed for injecting `service` within `execute_workflow` while testing.
135
+ workflow.service = service
136
+
137
+ return service
138
+
139
+ @property
140
+ def component(self) -> InfrahubComponent:
141
+ if not self._component:
142
+ raise InitializationError("Service is not initialized with a component")
143
+
144
+ return self._component
145
+
146
+ @property
147
+ def message_bus(self) -> InfrahubMessageBus:
148
+ if not self._message_bus:
149
+ raise InitializationError("Service is not initialized with a message bus")
150
+
151
+ return self._message_bus
152
+
153
+ @property
154
+ def workflow(self) -> InfrahubWorkflow:
155
+ if not self._workflow:
156
+ raise InitializationError("Service is not initialized with a workflow")
157
+
158
+ return self._workflow
159
+
160
+ @property
161
+ def cache(self) -> InfrahubCache:
162
+ if not self._cache:
163
+ raise InitializationError("Service is not initialized with a cache")
164
+
165
+ return self._cache
48
166
 
49
167
  @property
50
168
  def client(self) -> InfrahubClient:
@@ -53,9 +171,6 @@ class InfrahubServices:
53
171
 
54
172
  return self._client
55
173
 
56
- def set_client(self, client: InfrahubClient | None) -> None:
57
- self._client = client
58
-
59
174
  @property
60
175
  def database(self) -> InfrahubDatabase:
61
176
  if not self._database:
@@ -63,18 +178,7 @@ class InfrahubServices:
63
178
 
64
179
  return self._database
65
180
 
66
- async def initialize(self) -> None:
67
- """Initialize the Services"""
68
- await self.message_bus.initialize(service=self)
69
- await self.cache.initialize(service=self)
70
- await self.http.initialize(service=self)
71
- await self.component.initialize(service=self)
72
- await self.scheduler.initialize(service=self)
73
- await self.workflow.initialize(service=self)
74
- await self.event.initialize(service=self)
75
-
76
181
  async def shutdown(self) -> None:
77
- """Initialize the Services"""
78
182
  await self.scheduler.shutdown()
79
183
  await self.message_bus.shutdown()
80
184
 
@@ -84,24 +188,5 @@ class InfrahubServices:
84
188
  raise ValueError("Unable to determine routing key")
85
189
  await self.message_bus.publish(message, routing_key=routing_key, delay=delay, is_retry=is_retry)
86
190
 
87
- async def reply(self, message: InfrahubResponse, initiator: InfrahubMessage) -> None:
88
- if initiator.meta:
89
- message.meta.correlation_id = initiator.meta.correlation_id
90
- routing_key = initiator.meta.reply_to or ""
91
- await self.message_bus.reply(message, routing_key=routing_key)
92
-
93
-
94
- class ServiceManager:
95
- def __init__(self) -> None:
96
- self.service = InfrahubServices()
97
- self.send = self.service.send
98
-
99
- def prepare(self, service: InfrahubServices) -> None:
100
- self.service = service
101
- self.send = self.service.send
102
-
103
191
 
104
192
  ServiceFunction = Callable[[InfrahubServices], Awaitable[None]]
105
-
106
-
107
- services = ServiceManager()
@@ -1,34 +1,36 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from abc import ABC, abstractmethod
3
4
  from typing import TYPE_CHECKING, Optional
4
5
 
5
6
  if TYPE_CHECKING:
6
7
  from infrahub.message_bus.types import KVTTL
7
- from infrahub.services import InfrahubServices
8
8
 
9
9
 
10
- class InfrahubCache:
10
+ class InfrahubCache(ABC):
11
11
  """Base class for caching services"""
12
12
 
13
- async def initialize(self, service: InfrahubServices) -> None:
14
- """Initialize the cache"""
15
-
13
+ @abstractmethod
16
14
  async def delete(self, key: str) -> None:
17
15
  """Delete a key from the cache."""
18
16
  raise NotImplementedError()
19
17
 
18
+ @abstractmethod
20
19
  async def get(self, key: str) -> Optional[str]:
21
20
  """Retrieve a value from the cache."""
22
21
  raise NotImplementedError()
23
22
 
23
+ @abstractmethod
24
24
  async def get_values(self, keys: list[str]) -> list[Optional[str]]:
25
25
  """Return a list the values for requested keys."""
26
26
  raise NotImplementedError()
27
27
 
28
+ @abstractmethod
28
29
  async def list_keys(self, filter_pattern: str) -> list[str]:
29
30
  """Return a list of active keys that match the provided filter."""
30
31
  raise NotImplementedError()
31
32
 
33
+ @abstractmethod
32
34
  async def set(
33
35
  self, key: str, value: str, expires: Optional[KVTTL] = None, not_exists: bool = False
34
36
  ) -> Optional[bool]:
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import ssl
4
- from typing import TYPE_CHECKING, Optional
4
+ from typing import Optional
5
5
 
6
6
  import nats
7
7
 
@@ -9,26 +9,38 @@ from infrahub import config
9
9
  from infrahub.message_bus.types import KVTTL
10
10
  from infrahub.services.adapters.cache import InfrahubCache
11
11
 
12
- if TYPE_CHECKING:
13
- from infrahub.services import InfrahubServices
12
+ # Inherit from BaseModel to avoid implementing a `__init__` otherwise `cls(...)` fails.
14
13
 
15
14
 
16
15
  class NATSCache(InfrahubCache):
17
- def __init__(self) -> None:
18
- self.connection: nats.NATS
19
- self.jetstream: nats.js.JetStreamContext
20
- self.kv: dict[int, nats.js.kv.KeyValue]
21
-
16
+ connection: nats.NATS
17
+ jetstream: nats.js.JetStreamContext
18
+ kv: dict[int, nats.js.kv.KeyValue]
19
+ kv_buckets: dict[str, KVTTL]
20
+
21
+ def __init__(
22
+ self,
23
+ connection: nats.NATS,
24
+ jetstream: nats.js.JetStreamContext,
25
+ kv: dict[int, nats.js.kv.KeyValue],
26
+ kv_buckets: dict[str, KVTTL],
27
+ ):
28
+ self.connection = connection
29
+ self.jetstream = jetstream
30
+ self.kv = kv
31
+ self.kv_buckets = kv_buckets
32
+
33
+ @classmethod
34
+ async def new(cls) -> NATSCache:
22
35
  # FIXME: remove once NATS supports TTL for keys (2.11)
23
- self.kv_buckets = {
24
- self._tokenize_key_name("validator_execution_id:"): KVTTL.TWO_HOURS,
25
- self._tokenize_key_name("workers:primary:"): KVTTL.FIFTEEN,
26
- self._tokenize_key_name("workers:schema_hash:branch:"): KVTTL.TWO_HOURS,
27
- self._tokenize_key_name("workers:active:"): KVTTL.FIFTEEN,
28
- self._tokenize_key_name("workers:worker:"): KVTTL.TWO_HOURS,
36
+ kv_buckets = {
37
+ NATSCache._tokenize_key_name("validator_execution_id:"): KVTTL.TWO_HOURS,
38
+ NATSCache._tokenize_key_name("workers:primary:"): KVTTL.FIFTEEN,
39
+ NATSCache._tokenize_key_name("workers:schema_hash:branch:"): KVTTL.TWO_HOURS,
40
+ NATSCache._tokenize_key_name("workers:active:"): KVTTL.FIFTEEN,
41
+ NATSCache._tokenize_key_name("workers:worker:"): KVTTL.TWO_HOURS,
29
42
  }
30
43
 
31
- async def initialize(self, service: InfrahubServices) -> None:
32
44
  tls_context = None
33
45
  if config.SETTINGS.cache.tls_enabled:
34
46
  tls_context = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
@@ -38,25 +50,27 @@ class NATSCache(InfrahubCache):
38
50
  tls_context.check_hostname = False
39
51
  tls_context.verify_mode = ssl.CERT_NONE
40
52
 
41
- self.connection = await nats.connect(
53
+ connection = await nats.connect(
42
54
  f"nats://{config.SETTINGS.cache.address}:{config.SETTINGS.cache.service_port}",
43
55
  user=config.SETTINGS.cache.username,
44
56
  password=config.SETTINGS.cache.password,
45
57
  tls=tls_context,
46
58
  )
47
-
48
- self.jetstream = self.connection.jetstream()
59
+ jetstream = connection.jetstream()
49
60
 
50
61
  kv_config = nats.js.api.KeyValueConfig(bucket=f"kv_{config.SETTINGS.cache.database}")
51
- self.kv = {0: await self.jetstream.create_key_value(config=kv_config)}
62
+ kv = {0: await jetstream.create_key_value(config=kv_config)}
52
63
 
53
64
  # FIXME: remove once NATS supports TTL for keys (2.11)
54
65
  for ttl in KVTTL.variations():
55
66
  kv_config.bucket = f"kv_{config.SETTINGS.cache.database}_ttl_{ttl.name.lower()}"
56
67
  kv_config.ttl = ttl.value
57
- self.kv[ttl.value] = await self.jetstream.create_key_value(config=kv_config)
68
+ kv[ttl.value] = await jetstream.create_key_value(config=kv_config)
69
+
70
+ return cls(kv_buckets=kv_buckets, kv=kv, connection=connection, jetstream=jetstream)
58
71
 
59
- def _tokenize_key_name(self, key: str) -> str:
72
+ @staticmethod
73
+ def _tokenize_key_name(key: str) -> str:
60
74
  return key.replace(":", ".")
61
75
 
62
76
  # FIXME: remove once NATS supports TTL for keys (2.11)
@@ -121,7 +135,11 @@ class NATSCache(InfrahubCache):
121
135
  return [key.replace(".", ":") for key in keys]
122
136
 
123
137
  async def set(
124
- self, key: str, value: str, expires: Optional[KVTTL] = None, not_exists: bool = False
138
+ self,
139
+ key: str,
140
+ value: str,
141
+ expires: Optional[KVTTL] = None, # noqa: ARG002
142
+ not_exists: bool = False,
125
143
  ) -> Optional[bool]:
126
144
  key = self._tokenize_key_name(key)
127
145
  if not_exists:
@@ -4,7 +4,6 @@ import redis.asyncio as redis
4
4
 
5
5
  from infrahub import config
6
6
  from infrahub.message_bus.types import KVTTL
7
- from infrahub.services import InfrahubServices
8
7
  from infrahub.services.adapters.cache import InfrahubCache
9
8
 
10
9
 
@@ -20,9 +19,6 @@ class RedisCache(InfrahubCache):
20
19
  ssl_ca_certs=config.SETTINGS.cache.tls_ca_file,
21
20
  )
22
21
 
23
- async def initialize(self, service: InfrahubServices) -> None:
24
- pass
25
-
26
22
  async def delete(self, key: str) -> None:
27
23
  await self.connection.delete(key)
28
24
 
@@ -5,29 +5,18 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  from prefect.events import emit_event
7
7
 
8
- from infrahub.exceptions import InitializationError
9
-
10
8
  if TYPE_CHECKING:
11
9
  from infrahub.events import InfrahubEvent
12
- from infrahub.services import InfrahubServices
10
+ from infrahub.services import InfrahubMessageBus
13
11
 
14
12
 
15
13
  class InfrahubEventService:
16
14
  """Base class for infrahub event service"""
17
15
 
18
- def __init__(self) -> None:
19
- self._service: InfrahubServices | None = None
20
-
21
- @property
22
- def service(self) -> InfrahubServices:
23
- if not self._service:
24
- raise InitializationError("Event is not initialized with a service")
25
-
26
- return self._service
27
-
28
- async def initialize(self, service: InfrahubServices) -> None:
29
- """Initialize the event service"""
30
- self._service = service
16
+ def __init__(self, message_bus: InfrahubMessageBus | None = None) -> None:
17
+ # Ideally message_bus should not be optional, we let it like this for existing tests that
18
+ # pass without a bus as corresponding tested events do not send bus messages.
19
+ self.message_bus = message_bus
31
20
 
32
21
  async def send(self, event: InfrahubEvent) -> None:
33
22
  tasks = [self._send_bus(event=event), self._send_prefect(event=event)]
@@ -35,12 +24,15 @@ class InfrahubEventService:
35
24
 
36
25
  async def _send_bus(self, event: InfrahubEvent) -> None:
37
26
  for message in event.get_messages():
38
- await self.service.send(message=message)
27
+ if self.message_bus is None:
28
+ raise ValueError("InfrahubEventService.message_bus is None.")
29
+ await self.message_bus.send(message=message)
39
30
 
40
31
  async def _send_prefect(self, event: InfrahubEvent) -> None:
41
32
  emit_event(
33
+ id=event.meta.id,
42
34
  event=event.get_name(),
43
35
  resource=event.get_resource(),
44
36
  related=event.get_related(),
45
- payload=event.get_payload(),
37
+ payload=event.get_event_payload(),
46
38
  )
@@ -5,13 +5,8 @@ from typing import TYPE_CHECKING, Any
5
5
  if TYPE_CHECKING:
6
6
  import httpx
7
7
 
8
- from infrahub.services import InfrahubServices
9
-
10
8
 
11
9
  class InfrahubHTTP:
12
- async def initialize(self, service: InfrahubServices) -> None:
13
- """Initialize the HTTP adapter"""
14
-
15
10
  async def get(
16
11
  self,
17
12
  url: str,
@@ -2,30 +2,37 @@ from __future__ import annotations
2
2
 
3
3
  import ssl
4
4
  from functools import cached_property
5
- from typing import TYPE_CHECKING, Any
5
+ from typing import Any
6
6
 
7
7
  import httpx
8
8
 
9
9
  from infrahub import config
10
10
  from infrahub.exceptions import HTTPServerError, HTTPServerSSLError, HTTPServerTimeoutError
11
+ from infrahub.log import get_logger
11
12
  from infrahub.services.adapters.http import InfrahubHTTP
12
13
 
13
- if TYPE_CHECKING:
14
- from infrahub.services import InfrahubServices
14
+ log = get_logger()
15
15
 
16
16
 
17
17
  class HttpxAdapter(InfrahubHTTP):
18
- settings: config.HTTPSettings
19
- service: InfrahubServices
18
+ """The HttpxAdapter is a generic interface for InfrahubHTTP
20
19
 
21
- async def initialize(self, service: InfrahubServices) -> None:
22
- """Initialize the HTTP adapter"""
23
- self.service = service
24
- self.settings = config.SETTINGS.http
20
+ The class provides a way to send HTTP requests from Infrahub for example
21
+ when sending webhooks, telemetry data or when communicating with SSO
22
+ providers. The main purpose is to have a single location to manage
23
+ configuration and error handling with regards to HTTP traffic and
24
+ allow users to define configurations such as timeout, TLS options
25
+ and eventually proxy settings in one location."""
25
26
 
26
- # Cache the context during init, this is to avoid issue when a CA bundle might be accessible
27
- # when Infrahub initializes but then removed before the first external HTTP call is made.
28
- _ = self.tls_context
27
+ _settings: config.HTTPSettings | None = None
28
+
29
+ @property
30
+ def settings(self) -> config.HTTPSettings:
31
+ if self._settings:
32
+ return self._settings
33
+
34
+ self._settings = config.SETTINGS.http
35
+ return self._settings
29
36
 
30
37
  @cached_property
31
38
  def tls_context(self) -> ssl.SSLContext:
@@ -62,16 +69,16 @@ class HttpxAdapter(InfrahubHTTP):
62
69
  **params,
63
70
  )
64
71
  except ssl.SSLCertVerificationError as exc:
65
- self.service.log.info(f"TLS verification failed for connection to {url}")
72
+ log.info(f"TLS verification failed for connection to {url}")
66
73
  raise HTTPServerSSLError(message=f"Unable to validate TLS certificate for connection to {url}") from exc
67
74
  except httpx.ReadTimeout as exc:
68
- self.service.log.info(f"Connection timed out when trying to reach {url}")
75
+ log.info(f"Connection timed out when trying to reach {url}")
69
76
  raise HTTPServerTimeoutError(
70
77
  message=f"Connection to {url} timed out after {self.settings.timeout}"
71
78
  ) from exc
72
79
  except httpx.RequestError as exc:
73
80
  # Catch all error from httpx
74
- self.service.log.warning(f"Unhandled HTTP error for {url} ({exc})")
81
+ log.warning(f"Unhandled HTTP error for {url} ({exc})")
75
82
  raise HTTPServerError(message=f"Unknown http error when connecting to {url}") from exc
76
83
 
77
84
  return response
@@ -1,16 +1,19 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from abc import ABC, abstractmethod
3
4
  from typing import TYPE_CHECKING, Optional, TypeVar
4
5
 
6
+ from infrahub.message_bus.messages import ROUTING_KEY_MAP
7
+
5
8
  ResponseClass = TypeVar("ResponseClass")
6
9
 
7
10
  if TYPE_CHECKING:
8
- from infrahub.message_bus import InfrahubMessage
11
+ from infrahub.message_bus import InfrahubMessage, InfrahubResponse
9
12
  from infrahub.message_bus.types import MessageTTL
10
13
  from infrahub.services import InfrahubServices
11
14
 
12
15
 
13
- class InfrahubMessageBus:
16
+ class InfrahubMessageBus(ABC):
14
17
  DELIVER_TIMEOUT: int = 30 * 60 # 30 minutes
15
18
  worker_bindings: list[str] = [
16
19
  "check.*.*",
@@ -26,20 +29,34 @@ class InfrahubMessageBus:
26
29
  ]
27
30
  event_bindings: list[str] = ["refresh.registry.*"]
28
31
  broadcasted_event_bindings: list[str] = ["refresh.git.*"]
32
+ service: InfrahubServices
29
33
 
30
- async def initialize(self, service: InfrahubServices) -> None:
31
- """Initialize the Message bus"""
32
-
33
- async def shutdown(self) -> None:
34
+ async def shutdown(self) -> None: # noqa: B027 We want a default empty behavior, so it's ok to have an empty non-abstract method.
34
35
  """Shutdown the Message bus"""
35
36
 
37
+ @abstractmethod
36
38
  async def publish(
37
39
  self, message: InfrahubMessage, routing_key: str, delay: Optional[MessageTTL] = None, is_retry: bool = False
38
40
  ) -> None:
39
41
  raise NotImplementedError()
40
42
 
43
+ @abstractmethod
41
44
  async def reply(self, message: InfrahubMessage, routing_key: str) -> None:
42
45
  raise NotImplementedError()
43
46
 
47
+ @abstractmethod
44
48
  async def rpc(self, message: InfrahubMessage, response_class: type[ResponseClass]) -> ResponseClass:
45
49
  raise NotImplementedError()
50
+
51
+ async def send(self, message: InfrahubMessage, delay: Optional[MessageTTL] = None, is_retry: bool = False) -> None:
52
+ routing_key = ROUTING_KEY_MAP.get(type(message))
53
+ if not routing_key:
54
+ raise ValueError("Unable to determine routing key")
55
+ await self.publish(message, routing_key=routing_key, delay=delay, is_retry=is_retry)
56
+
57
+ # TODO rename it
58
+ async def reply_if_initiator_meta(self, message: InfrahubResponse, initiator: InfrahubMessage) -> None:
59
+ if initiator.meta:
60
+ message.meta.correlation_id = initiator.meta.correlation_id
61
+ routing_key = initiator.meta.reply_to or ""
62
+ await self.reply(message, routing_key=routing_key)
@@ -10,34 +10,36 @@ from infrahub.dependencies.registry import build_component_registry
10
10
  from infrahub.message_bus import InfrahubMessage, Meta
11
11
  from infrahub.message_bus.messages import ROUTING_KEY_MAP
12
12
  from infrahub.message_bus.operations import execute_message
13
- from infrahub.services import InfrahubServices
14
13
  from infrahub.services.adapters.message_bus import InfrahubMessageBus
15
14
 
16
15
  if TYPE_CHECKING:
17
- from infrahub.database import InfrahubDatabase
18
16
  from infrahub.message_bus.types import MessageTTL
19
17
 
20
18
  ResponseClass = TypeVar("ResponseClass")
21
19
 
22
20
 
23
21
  class BusSimulator(InfrahubMessageBus):
24
- def __init__(self, database: Optional[InfrahubDatabase] = None) -> None:
22
+ def __init__(self) -> None:
25
23
  self.messages: list[InfrahubMessage] = []
26
24
  self.messages_per_routing_key: dict[str, list[InfrahubMessage]] = {}
27
- self.service: InfrahubServices = InfrahubServices(database=database, message_bus=self)
28
25
  self.replies: dict[str, list[InfrahubMessage]] = defaultdict(list)
29
26
  build_component_registry()
30
27
 
31
28
  async def publish(
32
- self, message: InfrahubMessage, routing_key: str, delay: Optional[MessageTTL] = None, is_retry: bool = False
29
+ self,
30
+ message: InfrahubMessage,
31
+ routing_key: str,
32
+ delay: Optional[MessageTTL] = None, # noqa: ARG002
33
+ is_retry: bool = False, # noqa: ARG002
33
34
  ) -> None:
34
35
  self.messages.append(message)
35
36
  if routing_key not in self.messages_per_routing_key:
36
37
  self.messages_per_routing_key[routing_key] = []
37
38
  self.messages_per_routing_key[routing_key].append(message)
39
+ assert self.service is not None
38
40
  await execute_message(routing_key=routing_key, message_body=message.body, service=self.service)
39
41
 
40
- async def reply(self, message: InfrahubMessage, routing_key: str) -> None:
42
+ async def reply(self, message: InfrahubMessage, routing_key: str) -> None: # noqa: ARG002
41
43
  correlation_id = message.meta.correlation_id or "default"
42
44
  self.replies[correlation_id].append(message)
43
45