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
@@ -17,16 +17,19 @@ from prefect.logging import get_run_logger
17
17
  from prefect.states import Completed, Failed
18
18
 
19
19
  from infrahub import config
20
+ from infrahub.artifacts.models import CheckArtifactCreate
21
+ from infrahub.context import InfrahubContext # noqa: TC001 needed for prefect flow
20
22
  from infrahub.core import registry
21
23
  from infrahub.core.branch import Branch
22
24
  from infrahub.core.branch.tasks import merge_branch
23
- from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus, ValidatorConclusion
25
+ from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus, ValidatorConclusion, ValidatorState
24
26
  from infrahub.core.diff.coordinator import DiffCoordinator
25
27
  from infrahub.core.diff.model.diff import DiffElementType, SchemaConflict
26
28
  from infrahub.core.diff.model.path import NodeDiffFieldSummary
27
29
  from infrahub.core.integrity.object_conflict.conflict_recorder import ObjectConflictValidatorRecorder
28
30
  from infrahub.core.protocols import CoreDataCheck, CoreValidator
29
31
  from infrahub.core.protocols import CoreProposedChange as InternalCoreProposedChange
32
+ from infrahub.core.validators.checks_runner import run_checks_and_update_validator
30
33
  from infrahub.core.validators.determiner import ConstraintValidatorDeterminer
31
34
  from infrahub.core.validators.models.validate_migration import SchemaValidateMigrationData
32
35
  from infrahub.core.validators.tasks import schema_validate_migrations
@@ -39,6 +42,7 @@ from infrahub.message_bus import InfrahubMessage, messages
39
42
  from infrahub.message_bus.operations.requests.proposed_change import DefinitionSelect
40
43
  from infrahub.proposed_change.constants import ProposedChangeState
41
44
  from infrahub.proposed_change.models import (
45
+ RequestArtifactDefinitionCheck,
42
46
  RequestProposedChangeDataIntegrity,
43
47
  RequestProposedChangeRepositoryChecks,
44
48
  RequestProposedChangeRunGenerators,
@@ -46,8 +50,12 @@ from infrahub.proposed_change.models import (
46
50
  RequestProposedChangeUserTests,
47
51
  )
48
52
  from infrahub.pytest_plugin import InfrahubBackendPlugin
49
- from infrahub.services import services
50
- from infrahub.workflows.catalogue import COMPUTED_ATTRIBUTE_SETUP_PYTHON, REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS
53
+ from infrahub.services import InfrahubServices # noqa: TC001 needed for prefect flow
54
+ from infrahub.workflows.catalogue import (
55
+ COMPUTED_ATTRIBUTE_SETUP_PYTHON,
56
+ GIT_REPOSITORIES_CHECK_ARTIFACT_CREATE,
57
+ REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
58
+ )
51
59
  from infrahub.workflows.utils import add_tags
52
60
 
53
61
  if TYPE_CHECKING:
@@ -60,10 +68,10 @@ if TYPE_CHECKING:
60
68
 
61
69
  async def _proposed_change_transition_state(
62
70
  state: ProposedChangeState,
71
+ service: InfrahubServices,
63
72
  proposed_change: InternalCoreProposedChange | None = None,
64
73
  proposed_change_id: str | None = None,
65
74
  ) -> None:
66
- service = services.service
67
75
  async with service.database.start_session() as db:
68
76
  if proposed_change is None and proposed_change_id:
69
77
  proposed_change = await registry.manager.get_one(
@@ -96,8 +104,12 @@ async def _proposed_change_transition_state(
96
104
  # on_crashed=[proposed_change_transition_open], # type: ignore
97
105
  # on_cancellation=[proposed_change_transition_open], # type: ignore
98
106
  )
99
- async def merge_proposed_change(proposed_change_id: str, proposed_change_name: str) -> State: # pylint: disable=unused-argument
100
- service = services.service
107
+ async def merge_proposed_change(
108
+ proposed_change_id: str,
109
+ proposed_change_name: str, # noqa: ARG001
110
+ context: InfrahubContext,
111
+ service: InfrahubServices,
112
+ ) -> State:
101
113
  log = get_run_logger()
102
114
 
103
115
  await add_tags(nodes=[proposed_change_id])
@@ -118,14 +130,16 @@ async def merge_proposed_change(proposed_change_id: str, proposed_change_name: s
118
130
  and validation.conclusion.value.value != ValidatorConclusion.SUCCESS.value
119
131
  ):
120
132
  # Ignoring Data integrity checks as they are handled again later
121
- await _proposed_change_transition_state(proposed_change=proposed_change, state=ProposedChangeState.OPEN)
133
+ await _proposed_change_transition_state(
134
+ proposed_change=proposed_change, state=ProposedChangeState.OPEN, service=service
135
+ )
122
136
  return Failed(message="Unable to merge proposed change containing failing checks")
123
137
  if validator_kind == InfrahubKind.DATAVALIDATOR:
124
138
  data_checks = await validation.checks.get_peers(db=db, peer_type=CoreDataCheck)
125
139
  for check in data_checks.values():
126
140
  if check.conflicts.value and not check.keep_branch.value:
127
141
  await _proposed_change_transition_state(
128
- proposed_change=proposed_change, state=ProposedChangeState.OPEN
142
+ proposed_change=proposed_change, state=ProposedChangeState.OPEN, service=service
129
143
  )
130
144
  return Failed(
131
145
  message="Data conflicts found on branch and missing decisions about what branch to keep"
@@ -133,15 +147,19 @@ async def merge_proposed_change(proposed_change_id: str, proposed_change_name: s
133
147
 
134
148
  log.info("Proposed change is eligible to be merged")
135
149
  try:
136
- await merge_branch(branch=source_branch.name)
150
+ await merge_branch(branch=source_branch.name, context=context, service=service)
137
151
  except MergeFailedError as exc:
138
- await _proposed_change_transition_state(proposed_change=proposed_change, state=ProposedChangeState.OPEN)
152
+ await _proposed_change_transition_state(
153
+ proposed_change=proposed_change, state=ProposedChangeState.OPEN, service=service
154
+ )
139
155
  return Failed(message=f"Merge failure when trying to merge {exc.message}")
140
156
 
141
157
  log.info(f"Branch {source_branch.name} has been merged successfully")
142
158
 
143
- await _proposed_change_transition_state(proposed_change=proposed_change, state=ProposedChangeState.MERGED)
144
- await service.workflow.submit_workflow(workflow=COMPUTED_ATTRIBUTE_SETUP_PYTHON)
159
+ await _proposed_change_transition_state(
160
+ proposed_change=proposed_change, state=ProposedChangeState.MERGED, service=service
161
+ )
162
+ await service.workflow.submit_workflow(workflow=COMPUTED_ATTRIBUTE_SETUP_PYTHON, context=context)
145
163
  return Completed(message="proposed change merged successfully")
146
164
 
147
165
 
@@ -150,9 +168,7 @@ async def merge_proposed_change(proposed_change_id: str, proposed_change_name: s
150
168
  flow_run_name="Cancel all proposed change associated with branch {branch_name}",
151
169
  description="Cancel all Proposed change associated with a branch.",
152
170
  )
153
- async def cancel_proposed_changes_branch(branch_name: str) -> None:
154
- service = services.service
155
-
171
+ async def cancel_proposed_changes_branch(branch_name: str, service: InfrahubServices) -> None:
156
172
  await add_tags(branches=[branch_name])
157
173
 
158
174
  proposed_changed_opened = await service.client.filters(
@@ -169,13 +185,11 @@ async def cancel_proposed_changes_branch(branch_name: str) -> None:
169
185
  )
170
186
 
171
187
  for proposed_change in proposed_changed_opened + proposed_changed_closed:
172
- await cancel_proposed_change(proposed_change=proposed_change)
173
-
188
+ await cancel_proposed_change(proposed_change=proposed_change, service=service)
174
189
 
175
- @task(name="Cancel a propose change", description="Cancel a propose change", cache_policy=NONE)
176
- async def cancel_proposed_change(proposed_change: CoreProposedChange) -> None:
177
- service = services.service
178
190
 
191
+ @task(name="Cancel a propose change", description="Cancel a propose change", cache_policy=NONE) # type: ignore[arg-type]
192
+ async def cancel_proposed_change(proposed_change: CoreProposedChange, service: InfrahubServices) -> None:
179
193
  await add_tags(nodes=[proposed_change.id])
180
194
  log = get_run_logger()
181
195
 
@@ -189,11 +203,12 @@ async def cancel_proposed_change(proposed_change: CoreProposedChange) -> None:
189
203
  name="proposed-changed-data-integrity",
190
204
  flow_run_name="Triggers data integrity check",
191
205
  )
192
- async def run_proposed_change_data_integrity_check(model: RequestProposedChangeDataIntegrity) -> None:
206
+ async def run_proposed_change_data_integrity_check(
207
+ model: RequestProposedChangeDataIntegrity, service: InfrahubServices
208
+ ) -> None:
193
209
  """Triggers a data integrity validation check on the provided proposed change to start."""
194
210
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
195
211
 
196
- service = services.service
197
212
  async with service.database.start_transaction() as dbt:
198
213
  destination_branch = await registry.get_branch(db=dbt, branch=model.destination_branch)
199
214
  source_branch = await registry.get_branch(db=dbt, branch=model.source_branch)
@@ -207,8 +222,9 @@ async def run_proposed_change_data_integrity_check(model: RequestProposedChangeD
207
222
  name="proposed-changed-run-generator",
208
223
  flow_run_name="Run generators",
209
224
  )
210
- async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
211
- service = services.service
225
+ async def run_generators(
226
+ model: RequestProposedChangeRunGenerators, context: InfrahubContext, service: InfrahubServices
227
+ ) -> None:
212
228
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change], db_change=True)
213
229
 
214
230
  generators = await service.client.filters(
@@ -264,7 +280,7 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
264
280
  destination_branch=model.destination_branch,
265
281
  )
266
282
  msg.assign_meta(parent=model)
267
- await service.send(message=msg)
283
+ await service.message_bus.send(message=msg)
268
284
 
269
285
  next_messages: list[InfrahubMessage] = []
270
286
  if model.refresh_artifacts:
@@ -287,12 +303,14 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
287
303
  branch_diff=model.branch_diff,
288
304
  )
289
305
  await service.workflow.submit_workflow(
290
- workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS, parameters={"model": model_proposed_change_repo_checks}
306
+ workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
307
+ context=context,
308
+ parameters={"model": model_proposed_change_repo_checks},
291
309
  )
292
310
 
293
311
  for next_msg in next_messages:
294
312
  next_msg.assign_meta(parent=model)
295
- await service.send(message=next_msg)
313
+ await service.message_bus.send(message=next_msg)
296
314
 
297
315
 
298
316
  @flow(
@@ -300,11 +318,10 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
300
318
  flow_run_name="Process schema integrity",
301
319
  )
302
320
  async def run_proposed_change_schema_integrity_check(
303
- model: RequestProposedChangeSchemaIntegrity,
321
+ model: RequestProposedChangeSchemaIntegrity, service: InfrahubServices
304
322
  ) -> None:
305
323
  # For now, we retrieve the latest schema for each branch from the registry
306
324
  # In the future it would be good to generate the object SchemaUpdateValidationResult from message.branch_diff
307
- service = services.service
308
325
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
309
326
 
310
327
  source_schema = registry.schema.get_schema_branch(name=model.source_branch).duplicate()
@@ -331,7 +348,8 @@ async def run_proposed_change_schema_integrity_check(
331
348
  responses = await schema_validate_migrations(
332
349
  message=SchemaValidateMigrationData(
333
350
  branch=source_branch, schema_branch=candidate_schema, constraints=list(constraints)
334
- )
351
+ ),
352
+ service=service,
335
353
  )
336
354
 
337
355
  # TODO we need to report a failure if an error happened during the execution of a validator
@@ -393,8 +411,7 @@ async def _get_proposed_change_schema_integrity_constraints(
393
411
  name="proposed-changed-repository-checks",
394
412
  flow_run_name="Process user defined checks",
395
413
  )
396
- async def repository_checks(model: RequestProposedChangeRepositoryChecks) -> None:
397
- service = services.service
414
+ async def repository_checks(model: RequestProposedChangeRepositoryChecks, service: InfrahubServices) -> None:
398
415
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
399
416
 
400
417
  events: list[InfrahubMessage] = []
@@ -426,15 +443,14 @@ async def repository_checks(model: RequestProposedChangeRepositoryChecks) -> Non
426
443
  )
427
444
  for event in events:
428
445
  event.assign_meta(parent=model)
429
- await service.send(message=event)
446
+ await service.message_bus.send(message=event)
430
447
 
431
448
 
432
449
  @flow(
433
450
  name="proposed-changed-user-tests",
434
451
  flow_run_name="Run unit tests in repositories",
435
452
  )
436
- async def run_proposed_change_user_tests(model: RequestProposedChangeUserTests) -> None:
437
- service = services.service
453
+ async def run_proposed_change_user_tests(model: RequestProposedChangeUserTests, service: InfrahubServices) -> None:
438
454
  log = get_run_logger()
439
455
  await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
440
456
  proposed_change = await service.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=model.proposed_change)
@@ -493,3 +509,125 @@ async def run_proposed_change_user_tests(model: RequestProposedChangeUserTests)
493
509
 
494
510
  return_code = await asyncio.to_thread(_execute, worktree_directory, repository, proposed_change)
495
511
  log.info(msg=f"repository_tests_completed return_code={return_code}")
512
+
513
+
514
+ @flow(
515
+ name="artifacts-generation-validation",
516
+ flow_run_name="Validating generation of artifacts for {model.artifact_definition.definition_name}",
517
+ )
518
+ async def validate_artifacts_generation(model: RequestArtifactDefinitionCheck, service: InfrahubServices) -> None:
519
+ await add_tags(branches=[model.source_branch], nodes=[model.proposed_change], db_change=True)
520
+
521
+ log = get_run_logger()
522
+ artifact_definition = await service.client.get(
523
+ kind=InfrahubKind.ARTIFACTDEFINITION,
524
+ id=model.artifact_definition.definition_id,
525
+ branch=model.source_branch,
526
+ )
527
+ proposed_change = await service.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=model.proposed_change)
528
+
529
+ validator_name = f"Artifact Validator: {model.artifact_definition.definition_name}"
530
+
531
+ await proposed_change.validations.fetch()
532
+
533
+ validator = None
534
+ for relationship in proposed_change.validations.peers:
535
+ existing_validator = relationship.peer
536
+ if (
537
+ existing_validator.typename == InfrahubKind.ARTIFACTVALIDATOR
538
+ and existing_validator.definition.id == model.artifact_definition.definition_id
539
+ ):
540
+ validator = existing_validator
541
+
542
+ if validator:
543
+ validator.conclusion.value = ValidatorConclusion.UNKNOWN.value
544
+ validator.state.value = ValidatorState.QUEUED.value
545
+ validator.started_at.value = ""
546
+ validator.completed_at.value = ""
547
+ await validator.save()
548
+ else:
549
+ validator = await service.client.create(
550
+ kind=InfrahubKind.ARTIFACTVALIDATOR,
551
+ data={
552
+ "label": validator_name,
553
+ "proposed_change": model.proposed_change,
554
+ "definition": model.artifact_definition.definition_id,
555
+ },
556
+ )
557
+ await validator.save()
558
+
559
+ await artifact_definition.targets.fetch()
560
+ group = artifact_definition.targets.peer
561
+ await group.members.fetch()
562
+
563
+ existing_artifacts = await service.client.filters(
564
+ kind=InfrahubKind.ARTIFACT,
565
+ definition__ids=[model.artifact_definition.definition_id],
566
+ include=["object"],
567
+ branch=model.source_branch,
568
+ )
569
+ artifacts_by_member = {}
570
+ for artifact in existing_artifacts:
571
+ artifacts_by_member[artifact.object.peer.id] = artifact.id
572
+
573
+ repository = model.branch_diff.get_repository(repository_id=model.artifact_definition.repository_id)
574
+ impacted_artifacts = model.branch_diff.get_subscribers_ids(kind=InfrahubKind.ARTIFACT)
575
+
576
+ checks = []
577
+
578
+ for relationship in group.members.peers:
579
+ member = relationship.peer
580
+ artifact_id = artifacts_by_member.get(member.id)
581
+ if _should_render_artifact(
582
+ artifact_id=artifact_id,
583
+ managed_branch=model.source_branch_sync_with_git,
584
+ impacted_artifacts=impacted_artifacts,
585
+ ):
586
+ log.info(f"Trigger Artifact processing for {member.display_label}")
587
+
588
+ check_model = CheckArtifactCreate(
589
+ artifact_name=model.artifact_definition.artifact_name,
590
+ artifact_id=artifact_id,
591
+ artifact_definition=model.artifact_definition.definition_id,
592
+ commit=repository.source_commit,
593
+ content_type=model.artifact_definition.content_type,
594
+ transform_type=model.artifact_definition.transform_kind,
595
+ transform_location=model.artifact_definition.transform_location,
596
+ repository_id=repository.repository_id,
597
+ repository_name=repository.repository_name,
598
+ repository_kind=repository.kind,
599
+ branch_name=model.source_branch,
600
+ query=model.artifact_definition.query_name,
601
+ variables=member.extract(params=artifact_definition.parameters.value),
602
+ target_id=member.id,
603
+ target_name=member.display_label,
604
+ timeout=model.artifact_definition.timeout,
605
+ validator_id=validator.id,
606
+ )
607
+
608
+ checks.append(
609
+ service.workflow.execute_workflow(
610
+ workflow=GIT_REPOSITORIES_CHECK_ARTIFACT_CREATE,
611
+ parameters={"model": check_model},
612
+ expected_return=ValidatorConclusion,
613
+ )
614
+ )
615
+
616
+ await run_checks_and_update_validator(checks, validator)
617
+
618
+
619
+ def _should_render_artifact(artifact_id: str | None, managed_branch: bool, impacted_artifacts: list[str]) -> bool: # noqa: ARG001
620
+ """Returns a boolean to indicate if an artifact should be generated or not.
621
+ Will return true if:
622
+ * The artifact_id wasn't set which could be that it's a new object that doesn't have a previous artifact
623
+ * The source brance is not data only which would indicate that it could contain updates in git to the transform
624
+ * The artifact_id exists in the impacted_artifacts list
625
+ Will return false if:
626
+ * The source branch is a data only branch and the artifact_id exists and is not in the impacted list
627
+ """
628
+
629
+ # if not artifact_id or managed_branch:
630
+ # return True
631
+ # return artifact_id in impacted_artifacts
632
+ # Temporary workaround tracked in https://github.com/opsmill/infrahub/issues/4991
633
+ return True
infrahub/pytest_plugin.py CHANGED
@@ -52,7 +52,7 @@ class InfrahubBackendPlugin:
52
52
 
53
53
  return validator, True
54
54
 
55
- def pytest_collection_modifyitems(self, session: Session, config: Config, items: list[Item]) -> None: # pylint: disable=unused-argument
55
+ def pytest_collection_modifyitems(self, session: Session, config: Config, items: list[Item]) -> None: # noqa: ARG002
56
56
  """This function is called after item collection and gives the opportunity to work on the collection before sending the items for testing.
57
57
 
58
58
  All items without an "infrahub" marker will be discarded. Items will also be re-ordered to be run in a specific order:
@@ -82,7 +82,7 @@ class InfrahubBackendPlugin:
82
82
  filtered_items.sort(key=sort_key)
83
83
  items[:] = filtered_items
84
84
 
85
- def pytest_collection_finish(self, session: Session) -> None: # pylint: disable=unused-argument
85
+ def pytest_collection_finish(self, session: Session) -> None: # noqa: ARG002
86
86
  """This function is called when tests have been collected and modified, meaning they are ready to be run."""
87
87
  self.proposed_change = self.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=self.proposed_change_id)
88
88
  self.proposed_change.validations.fetch()
@@ -95,7 +95,7 @@ class InfrahubBackendPlugin:
95
95
  check = relationship.peer
96
96
  self.checks[check.origin.value] = check
97
97
 
98
- def pytest_runtestloop(self, session: Session) -> Optional[object]: # pylint: disable=unused-argument,useless-return
98
+ def pytest_runtestloop(self, session: Session) -> Optional[object]: # noqa: ARG002
99
99
  """This function is called when the test loop is being run."""
100
100
  self.validator.conclusion.value = "unknown"
101
101
  self.validator.state.value = "in_progress"
@@ -144,7 +144,7 @@ class InfrahubBackendPlugin:
144
144
  # Workaround for https://github.com/opsmill/infrahub/issues/2184
145
145
  check.update(do_full_update=True)
146
146
 
147
- def pytest_sessionfinish(self, session: Session) -> None: # pylint: disable=unused-argument
147
+ def pytest_sessionfinish(self, session: Session) -> None: # noqa: ARG002
148
148
  """Set the final RepositoryValidator details after completing the test session."""
149
149
  conclusion = "success"
150
150
 
infrahub/server.py CHANGED
@@ -33,7 +33,7 @@ from infrahub.graphql.api.endpoints import router as graphql_router
33
33
  from infrahub.lock import initialize_lock
34
34
  from infrahub.log import clear_log_context, get_logger, set_log_data
35
35
  from infrahub.middleware import InfrahubCORSMiddleware
36
- from infrahub.services import InfrahubServices, services
36
+ from infrahub.services import InfrahubServices
37
37
  from infrahub.services.adapters.cache.nats import NATSCache
38
38
  from infrahub.services.adapters.cache.redis import RedisCache
39
39
  from infrahub.services.adapters.message_bus.nats import NATSMessageBus
@@ -70,26 +70,27 @@ async def app_initialization(application: FastAPI, enable_scheduler: bool = True
70
70
  if config.SETTINGS.workflow.driver == config.WorkflowDriver.WORKER
71
71
  else WorkflowLocalExecution()
72
72
  )
73
-
73
+ component_type = ComponentType.API_SERVER
74
74
  message_bus = config.OVERRIDE.message_bus or (
75
- NATSMessageBus() if config.SETTINGS.broker.driver == config.BrokerDriver.NATS else RabbitMQMessageBus()
75
+ await NATSMessageBus.new(component_type=component_type)
76
+ if config.SETTINGS.broker.driver == config.BrokerDriver.NATS
77
+ else await RabbitMQMessageBus.new(component_type=component_type)
76
78
  )
77
79
  cache = config.OVERRIDE.cache or (
78
- NATSCache() if config.SETTINGS.cache.driver == config.CacheDriver.NATS else RedisCache()
80
+ await NATSCache.new() if config.SETTINGS.cache.driver == config.CacheDriver.NATS else RedisCache()
79
81
  )
80
- service = InfrahubServices(
82
+ service = await InfrahubServices.new(
81
83
  cache=cache,
82
84
  database=database,
83
85
  message_bus=message_bus,
84
86
  workflow=workflow,
85
- component_type=ComponentType.API_SERVER,
87
+ component_type=component_type,
86
88
  )
87
- await service.initialize()
88
89
  initialize_lock(service=service)
89
90
  # We must initialize DB after initialize lock and initialize lock depends on cache initialization
90
91
  async with application.state.db.start_session() as db:
91
92
  await initialization(db=db)
92
- services.prepare(service=service)
93
+
93
94
  application.state.service = service
94
95
  application.state.response_delay = config.SETTINGS.miscellaneous.response_delay
95
96
  if enable_scheduler:
@@ -97,7 +98,7 @@ async def app_initialization(application: FastAPI, enable_scheduler: bool = True
97
98
 
98
99
 
99
100
  async def shutdown(application: FastAPI) -> None:
100
- await services.service.shutdown()
101
+ await application.state.service.shutdown()
101
102
  await application.state.db.close()
102
103
 
103
104
 
@@ -118,7 +119,7 @@ app = FastAPI(
118
119
  )
119
120
 
120
121
 
121
- def server_request_hook(span: Span, scope: dict) -> None: # pylint: disable=unused-argument
122
+ def server_request_hook(span: Span, scope: dict) -> None: # noqa: ARG001
122
123
  if span and span.is_recording():
123
124
  span.set_attribute("worker", WORKER_IDENTITY)
124
125
 
@@ -217,5 +218,5 @@ async def documentation() -> RedirectResponse:
217
218
 
218
219
 
219
220
  @app.get("/{rest_of_path:path}", include_in_schema=False)
220
- async def react_app(req: Request, rest_of_path: str) -> Response: # pylint: disable=unused-argument
221
+ async def react_app(req: Request, rest_of_path: str) -> Response: # noqa: ARG001
221
222
  return templates.TemplateResponse("index.html", {"request": req})