infrahub-server 1.1.6__py3-none-any.whl → 1.2.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (407) hide show
  1. infrahub/api/artifact.py +16 -4
  2. infrahub/api/dependencies.py +8 -0
  3. infrahub/api/oauth2.py +0 -1
  4. infrahub/api/oidc.py +0 -1
  5. infrahub/api/query.py +18 -7
  6. infrahub/api/schema.py +32 -6
  7. infrahub/api/transformation.py +12 -5
  8. infrahub/{message_bus/messages/check_artifact_create.py → artifacts/models.py} +5 -3
  9. infrahub/{message_bus/operations/check/artifact.py → artifacts/tasks.py} +26 -25
  10. infrahub/cli/__init__.py +0 -2
  11. infrahub/cli/db.py +6 -7
  12. infrahub/cli/events.py +8 -3
  13. infrahub/cli/git_agent.py +9 -7
  14. infrahub/cli/tasks.py +4 -6
  15. infrahub/computed_attribute/models.py +1 -1
  16. infrahub/computed_attribute/tasks.py +64 -17
  17. infrahub/computed_attribute/triggers.py +90 -0
  18. infrahub/config.py +1 -1
  19. infrahub/context.py +39 -0
  20. infrahub/core/account.py +5 -8
  21. infrahub/core/attribute.py +54 -22
  22. infrahub/core/branch/models.py +4 -4
  23. infrahub/core/branch/tasks.py +137 -129
  24. infrahub/core/changelog/__init__.py +0 -0
  25. infrahub/core/changelog/diff.py +283 -0
  26. infrahub/core/changelog/models.py +499 -0
  27. infrahub/core/constants/__init__.py +43 -2
  28. infrahub/core/constants/infrahubkind.py +1 -0
  29. infrahub/core/constants/schema.py +2 -0
  30. infrahub/core/diff/combiner.py +12 -8
  31. infrahub/core/diff/coordinator.py +49 -70
  32. infrahub/core/diff/data_check_synchronizer.py +86 -7
  33. infrahub/core/diff/enricher/aggregated.py +3 -3
  34. infrahub/core/diff/enricher/cardinality_one.py +7 -7
  35. infrahub/core/diff/enricher/hierarchy.py +22 -7
  36. infrahub/core/diff/enricher/labels.py +19 -4
  37. infrahub/core/diff/enricher/path_identifier.py +7 -9
  38. infrahub/core/diff/enricher/summary_counts.py +3 -1
  39. infrahub/core/diff/merger/merger.py +8 -4
  40. infrahub/core/diff/model/path.py +76 -35
  41. infrahub/core/diff/parent_node_adder.py +78 -0
  42. infrahub/core/diff/payload_builder.py +13 -2
  43. infrahub/core/diff/query/all_conflicts.py +6 -3
  44. infrahub/core/diff/query/artifact.py +1 -1
  45. infrahub/core/diff/query/delete_query.py +1 -1
  46. infrahub/core/diff/query/diff_get.py +3 -2
  47. infrahub/core/diff/query/diff_summary.py +1 -1
  48. infrahub/core/diff/query/field_specifiers.py +3 -1
  49. infrahub/core/diff/query/field_summary.py +3 -2
  50. infrahub/core/diff/query/filters.py +14 -3
  51. infrahub/core/diff/query/get_conflict_query.py +1 -1
  52. infrahub/core/diff/query/has_conflicts_query.py +6 -3
  53. infrahub/core/diff/query/merge.py +3 -3
  54. infrahub/core/diff/query/{drop_tracking_id.py → merge_tracking_id.py} +4 -4
  55. infrahub/core/diff/query/roots_metadata.py +9 -2
  56. infrahub/core/diff/query/save.py +233 -142
  57. infrahub/core/diff/query/summary_counts_enricher.py +267 -0
  58. infrahub/core/diff/query/time_range_query.py +3 -2
  59. infrahub/core/diff/query/update_conflict_query.py +1 -1
  60. infrahub/core/diff/query_parser.py +49 -24
  61. infrahub/core/diff/repository/deserializer.py +32 -28
  62. infrahub/core/diff/repository/repository.py +215 -41
  63. infrahub/core/diff/tasks.py +13 -12
  64. infrahub/core/enums.py +1 -1
  65. infrahub/core/graph/__init__.py +1 -1
  66. infrahub/core/graph/index.py +3 -0
  67. infrahub/core/integrity/object_conflict/conflict_recorder.py +1 -1
  68. infrahub/core/ipam/reconciler.py +1 -1
  69. infrahub/core/ipam/tasks.py +2 -3
  70. infrahub/core/manager.py +20 -15
  71. infrahub/core/merge.py +5 -2
  72. infrahub/core/migrations/graph/__init__.py +4 -0
  73. infrahub/core/migrations/graph/m001_add_version_to_graph.py +1 -1
  74. infrahub/core/migrations/graph/m002_attribute_is_default.py +2 -2
  75. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +2 -2
  76. infrahub/core/migrations/graph/m004_add_attr_documentation.py +1 -1
  77. infrahub/core/migrations/graph/m005_add_rel_read_only.py +1 -1
  78. infrahub/core/migrations/graph/m006_add_rel_on_delete.py +1 -1
  79. infrahub/core/migrations/graph/m007_add_rel_allow_override.py +1 -1
  80. infrahub/core/migrations/graph/m008_add_human_friendly_id.py +1 -1
  81. infrahub/core/migrations/graph/m009_add_generate_profile_attr.py +1 -1
  82. infrahub/core/migrations/graph/m010_add_generate_profile_attr_generic.py +1 -1
  83. infrahub/core/migrations/graph/m011_remove_profile_relationship_schema.py +2 -2
  84. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -23
  85. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -11
  86. infrahub/core/migrations/graph/m014_remove_index_attr_value.py +2 -2
  87. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
  88. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
  89. infrahub/core/migrations/graph/m017_add_core_profile.py +1 -1
  90. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -2
  91. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
  92. infrahub/core/migrations/graph/m020_add_generate_template_attr.py +48 -0
  93. infrahub/core/migrations/query/attribute_add.py +1 -1
  94. infrahub/core/migrations/query/attribute_rename.py +1 -1
  95. infrahub/core/migrations/query/delete_element_in_schema.py +1 -1
  96. infrahub/core/migrations/query/node_duplicate.py +39 -19
  97. infrahub/core/migrations/query/relationship_duplicate.py +1 -1
  98. infrahub/core/migrations/query/schema_attribute_update.py +1 -1
  99. infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
  100. infrahub/core/migrations/schema/node_remove.py +27 -13
  101. infrahub/core/migrations/schema/tasks.py +5 -5
  102. infrahub/core/migrations/shared.py +4 -4
  103. infrahub/core/models.py +7 -8
  104. infrahub/core/node/__init__.py +170 -46
  105. infrahub/core/node/base.py +1 -1
  106. infrahub/core/node/constraints/grouped_uniqueness.py +9 -2
  107. infrahub/core/node/delete_validator.py +4 -4
  108. infrahub/core/node/ipam.py +13 -8
  109. infrahub/core/node/permissions.py +4 -0
  110. infrahub/core/node/resource_manager/ip_prefix_pool.py +8 -5
  111. infrahub/core/node/standard.py +3 -5
  112. infrahub/core/property.py +1 -1
  113. infrahub/core/protocols.py +6 -0
  114. infrahub/core/protocols_base.py +4 -2
  115. infrahub/core/query/__init__.py +2 -5
  116. infrahub/core/query/attribute.py +9 -9
  117. infrahub/core/query/branch.py +5 -5
  118. infrahub/core/query/delete.py +1 -1
  119. infrahub/core/query/diff.py +45 -7
  120. infrahub/core/query/ipam.py +4 -4
  121. infrahub/core/query/node.py +19 -14
  122. infrahub/core/query/relationship.py +213 -26
  123. infrahub/core/query/resource_manager.py +13 -11
  124. infrahub/core/query/standard_node.py +6 -6
  125. infrahub/core/query/task.py +3 -3
  126. infrahub/core/query/task_log.py +1 -1
  127. infrahub/core/query/utils.py +5 -5
  128. infrahub/core/registry.py +0 -2
  129. infrahub/core/relationship/constraints/count.py +1 -1
  130. infrahub/core/relationship/constraints/peer_kind.py +1 -1
  131. infrahub/core/relationship/model.py +76 -38
  132. infrahub/core/schema/__init__.py +6 -4
  133. infrahub/core/schema/attribute_schema.py +8 -0
  134. infrahub/core/schema/basenode_schema.py +13 -3
  135. infrahub/core/schema/definitions/core/__init__.py +153 -0
  136. infrahub/core/schema/definitions/core/account.py +168 -0
  137. infrahub/core/schema/definitions/core/artifact.py +127 -0
  138. infrahub/core/schema/definitions/core/builtin.py +21 -0
  139. infrahub/core/schema/definitions/core/check.py +60 -0
  140. infrahub/core/schema/definitions/core/generator.py +96 -0
  141. infrahub/core/schema/definitions/core/graphql_query.py +77 -0
  142. infrahub/core/schema/definitions/core/group.py +105 -0
  143. infrahub/core/schema/definitions/core/ipam.py +252 -0
  144. infrahub/core/schema/definitions/core/lineage.py +17 -0
  145. infrahub/core/schema/definitions/core/menu.py +46 -0
  146. infrahub/core/schema/definitions/core/permission.py +161 -0
  147. infrahub/core/schema/definitions/core/profile.py +29 -0
  148. infrahub/core/schema/definitions/core/propose_change.py +88 -0
  149. infrahub/core/schema/definitions/core/propose_change_comment.py +188 -0
  150. infrahub/core/schema/definitions/core/propose_change_validator.py +326 -0
  151. infrahub/core/schema/definitions/core/repository.py +280 -0
  152. infrahub/core/schema/definitions/core/resource_pool.py +180 -0
  153. infrahub/core/schema/definitions/core/template.py +12 -0
  154. infrahub/core/schema/definitions/core/transform.py +87 -0
  155. infrahub/core/schema/definitions/core/webhook.py +108 -0
  156. infrahub/core/schema/definitions/internal.py +16 -0
  157. infrahub/core/schema/generated/genericnode_schema.py +5 -0
  158. infrahub/core/schema/generated/node_schema.py +5 -0
  159. infrahub/core/schema/generic_schema.py +5 -1
  160. infrahub/core/schema/manager.py +45 -42
  161. infrahub/core/schema/node_schema.py +4 -0
  162. infrahub/core/schema/profile_schema.py +4 -0
  163. infrahub/core/schema/relationship_schema.py +10 -2
  164. infrahub/core/schema/schema_branch.py +260 -16
  165. infrahub/core/schema/template_schema.py +36 -0
  166. infrahub/core/task/user_task.py +7 -5
  167. infrahub/core/timestamp.py +3 -3
  168. infrahub/core/utils.py +3 -2
  169. infrahub/core/validators/attribute/choices.py +1 -1
  170. infrahub/core/validators/attribute/enum.py +1 -1
  171. infrahub/core/validators/attribute/kind.py +1 -1
  172. infrahub/core/validators/attribute/length.py +1 -1
  173. infrahub/core/validators/attribute/optional.py +1 -1
  174. infrahub/core/validators/attribute/regex.py +1 -1
  175. infrahub/core/validators/attribute/unique.py +1 -1
  176. infrahub/core/validators/checks_runner.py +37 -0
  177. infrahub/core/validators/node/generate_profile.py +1 -1
  178. infrahub/core/validators/node/hierarchy.py +1 -1
  179. infrahub/core/validators/query.py +1 -1
  180. infrahub/core/validators/relationship/count.py +1 -1
  181. infrahub/core/validators/relationship/optional.py +1 -1
  182. infrahub/core/validators/relationship/peer.py +1 -1
  183. infrahub/core/validators/tasks.py +8 -6
  184. infrahub/core/validators/uniqueness/query.py +20 -17
  185. infrahub/database/__init__.py +16 -2
  186. infrahub/database/memgraph.py +1 -1
  187. infrahub/dependencies/builder/constraint/grouped/node_runner.py +0 -2
  188. infrahub/dependencies/builder/diff/combiner.py +1 -1
  189. infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
  190. infrahub/dependencies/builder/diff/coordinator.py +0 -2
  191. infrahub/dependencies/builder/diff/deserializer.py +4 -2
  192. infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
  193. infrahub/dependencies/builder/diff/enricher/summary_counts.py +1 -1
  194. infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
  195. infrahub/events/artifact_action.py +76 -0
  196. infrahub/events/branch_action.py +50 -21
  197. infrahub/events/group_action.py +117 -0
  198. infrahub/events/models.py +164 -51
  199. infrahub/events/node_action.py +70 -8
  200. infrahub/events/repository_action.py +8 -8
  201. infrahub/events/schema_action.py +21 -8
  202. infrahub/exceptions.py +9 -0
  203. infrahub/generators/models.py +1 -0
  204. infrahub/generators/tasks.py +34 -15
  205. infrahub/git/base.py +3 -5
  206. infrahub/git/constants.py +0 -1
  207. infrahub/git/integrator.py +60 -36
  208. infrahub/git/models.py +80 -1
  209. infrahub/git/repository.py +7 -8
  210. infrahub/git/tasks.py +432 -112
  211. infrahub/git_credential/helper.py +2 -3
  212. infrahub/graphql/analyzer.py +572 -11
  213. infrahub/graphql/app.py +34 -26
  214. infrahub/graphql/auth/query_permission_checker/anonymous_checker.py +5 -5
  215. infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +4 -4
  216. infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +4 -4
  217. infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +28 -35
  218. infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -5
  219. infrahub/graphql/context.py +33 -0
  220. infrahub/graphql/enums.py +1 -1
  221. infrahub/graphql/initialization.py +5 -1
  222. infrahub/graphql/loaders/node.py +2 -2
  223. infrahub/graphql/manager.py +63 -63
  224. infrahub/graphql/mutations/account.py +20 -13
  225. infrahub/graphql/mutations/artifact_definition.py +16 -12
  226. infrahub/graphql/mutations/branch.py +86 -40
  227. infrahub/graphql/mutations/computed_attribute.py +24 -13
  228. infrahub/graphql/mutations/diff.py +54 -14
  229. infrahub/graphql/mutations/diff_conflict.py +14 -8
  230. infrahub/graphql/mutations/generator.py +83 -0
  231. infrahub/graphql/mutations/graphql_query.py +19 -11
  232. infrahub/graphql/mutations/ipam.py +25 -23
  233. infrahub/graphql/mutations/main.py +243 -50
  234. infrahub/graphql/mutations/menu.py +10 -10
  235. infrahub/graphql/mutations/proposed_change.py +36 -28
  236. infrahub/graphql/mutations/relationship.py +343 -104
  237. infrahub/graphql/mutations/repository.py +41 -35
  238. infrahub/graphql/mutations/resource_manager.py +26 -26
  239. infrahub/graphql/mutations/schema.py +66 -33
  240. infrahub/graphql/mutations/tasks.py +16 -10
  241. infrahub/graphql/parser.py +1 -1
  242. infrahub/graphql/permissions.py +3 -10
  243. infrahub/graphql/queries/account.py +22 -18
  244. infrahub/graphql/queries/branch.py +6 -4
  245. infrahub/graphql/queries/diff/tree.py +63 -52
  246. infrahub/graphql/queries/event.py +115 -0
  247. infrahub/graphql/queries/internal.py +3 -3
  248. infrahub/graphql/queries/ipam.py +23 -18
  249. infrahub/graphql/queries/relationship.py +11 -10
  250. infrahub/graphql/queries/resource_manager.py +43 -27
  251. infrahub/graphql/queries/search.py +9 -8
  252. infrahub/graphql/queries/status.py +12 -9
  253. infrahub/graphql/queries/task.py +11 -9
  254. infrahub/graphql/resolvers/resolver.py +69 -43
  255. infrahub/graphql/resolvers/single_relationship.py +16 -10
  256. infrahub/graphql/schema.py +4 -0
  257. infrahub/graphql/subscription/__init__.py +1 -1
  258. infrahub/graphql/subscription/events.py +1 -1
  259. infrahub/graphql/subscription/graphql_query.py +8 -8
  260. infrahub/graphql/types/branch.py +2 -2
  261. infrahub/graphql/types/common.py +6 -1
  262. infrahub/graphql/types/context.py +12 -0
  263. infrahub/graphql/types/enums.py +2 -0
  264. infrahub/graphql/types/event.py +158 -0
  265. infrahub/graphql/types/interface.py +2 -2
  266. infrahub/graphql/types/node.py +3 -3
  267. infrahub/graphql/types/permission.py +2 -2
  268. infrahub/graphql/types/relationship.py +3 -3
  269. infrahub/graphql/types/standard_node.py +9 -11
  270. infrahub/graphql/utils.py +28 -182
  271. infrahub/groups/tasks.py +2 -3
  272. infrahub/lock.py +21 -21
  273. infrahub/menu/generator.py +0 -1
  274. infrahub/menu/menu.py +116 -138
  275. infrahub/menu/models.py +4 -4
  276. infrahub/message_bus/__init__.py +11 -13
  277. infrahub/message_bus/messages/__init__.py +0 -14
  278. infrahub/message_bus/messages/check_generator_run.py +1 -3
  279. infrahub/message_bus/messages/event_branch_merge.py +3 -0
  280. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +6 -0
  281. infrahub/message_bus/messages/request_proposedchange_pipeline.py +2 -0
  282. infrahub/message_bus/messages/send_echo_request.py +1 -1
  283. infrahub/message_bus/operations/__init__.py +4 -13
  284. infrahub/message_bus/operations/check/__init__.py +2 -2
  285. infrahub/message_bus/operations/check/generator.py +1 -3
  286. infrahub/message_bus/operations/event/branch.py +7 -3
  287. infrahub/message_bus/operations/event/schema.py +1 -1
  288. infrahub/message_bus/operations/event/worker.py +0 -3
  289. infrahub/message_bus/operations/finalize/validator.py +1 -1
  290. infrahub/message_bus/operations/git/file.py +2 -2
  291. infrahub/message_bus/operations/git/repository.py +1 -1
  292. infrahub/message_bus/operations/requests/__init__.py +0 -4
  293. infrahub/message_bus/operations/requests/generator_definition.py +2 -4
  294. infrahub/message_bus/operations/requests/proposed_change.py +37 -20
  295. infrahub/message_bus/operations/send/echo.py +1 -1
  296. infrahub/message_bus/types.py +1 -1
  297. infrahub/permissions/__init__.py +2 -1
  298. infrahub/permissions/globals.py +15 -0
  299. infrahub/permissions/types.py +26 -0
  300. infrahub/pools/prefix.py +29 -165
  301. infrahub/prefect_server/__init__.py +0 -0
  302. infrahub/prefect_server/app.py +18 -0
  303. infrahub/prefect_server/database.py +20 -0
  304. infrahub/prefect_server/events.py +28 -0
  305. infrahub/prefect_server/models.py +46 -0
  306. infrahub/proposed_change/models.py +18 -1
  307. infrahub/proposed_change/tasks.py +195 -53
  308. infrahub/pytest_plugin.py +4 -4
  309. infrahub/server.py +13 -12
  310. infrahub/services/__init__.py +148 -63
  311. infrahub/services/adapters/cache/__init__.py +11 -11
  312. infrahub/services/adapters/cache/nats.py +42 -25
  313. infrahub/services/adapters/cache/redis.py +3 -11
  314. infrahub/services/adapters/event/__init__.py +10 -18
  315. infrahub/services/adapters/http/__init__.py +0 -5
  316. infrahub/services/adapters/http/httpx.py +22 -15
  317. infrahub/services/adapters/message_bus/__init__.py +25 -8
  318. infrahub/services/adapters/message_bus/local.py +9 -7
  319. infrahub/services/adapters/message_bus/nats.py +14 -8
  320. infrahub/services/adapters/message_bus/rabbitmq.py +23 -10
  321. infrahub/services/adapters/workflow/__init__.py +11 -8
  322. infrahub/services/adapters/workflow/local.py +27 -6
  323. infrahub/services/adapters/workflow/worker.py +23 -7
  324. infrahub/services/component.py +43 -40
  325. infrahub/services/protocols.py +7 -7
  326. infrahub/services/scheduler.py +30 -29
  327. infrahub/storage.py +2 -4
  328. infrahub/task_manager/constants.py +1 -1
  329. infrahub/task_manager/event.py +261 -0
  330. infrahub/task_manager/models.py +147 -3
  331. infrahub/task_manager/task.py +1 -1
  332. infrahub/tasks/artifact.py +19 -18
  333. infrahub/tasks/registry.py +1 -1
  334. infrahub/tasks/telemetry.py +13 -14
  335. infrahub/transformations/tasks.py +3 -5
  336. infrahub/trigger/__init__.py +0 -0
  337. infrahub/trigger/catalogue.py +16 -0
  338. infrahub/trigger/constants.py +9 -0
  339. infrahub/trigger/models.py +105 -0
  340. infrahub/trigger/tasks.py +91 -0
  341. infrahub/types.py +1 -1
  342. infrahub/utils.py +1 -1
  343. infrahub/webhook/constants.py +0 -2
  344. infrahub/webhook/models.py +161 -40
  345. infrahub/webhook/tasks.py +123 -202
  346. infrahub/webhook/triggers.py +27 -0
  347. infrahub/workers/infrahub_async.py +36 -25
  348. infrahub/workers/utils.py +63 -0
  349. infrahub/workflows/catalogue.py +71 -52
  350. infrahub/workflows/initialization.py +14 -8
  351. infrahub/workflows/models.py +28 -4
  352. infrahub/workflows/utils.py +1 -1
  353. infrahub_sdk/client.py +8 -0
  354. infrahub_sdk/ctl/branch.py +3 -2
  355. infrahub_sdk/ctl/check.py +3 -3
  356. infrahub_sdk/ctl/cli_commands.py +16 -11
  357. infrahub_sdk/ctl/exceptions.py +0 -6
  358. infrahub_sdk/ctl/exporter.py +1 -1
  359. infrahub_sdk/ctl/generator.py +5 -5
  360. infrahub_sdk/ctl/importer.py +3 -2
  361. infrahub_sdk/ctl/menu.py +1 -1
  362. infrahub_sdk/ctl/object.py +1 -1
  363. infrahub_sdk/ctl/repository.py +23 -15
  364. infrahub_sdk/ctl/schema.py +2 -2
  365. infrahub_sdk/ctl/utils.py +4 -19
  366. infrahub_sdk/ctl/validate.py +2 -1
  367. infrahub_sdk/exceptions.py +12 -0
  368. infrahub_sdk/generator.py +3 -0
  369. infrahub_sdk/node.py +4 -4
  370. infrahub_sdk/protocols.py +21 -8
  371. infrahub_sdk/schema/__init__.py +14 -2
  372. infrahub_sdk/schema/main.py +7 -0
  373. infrahub_sdk/task/__init__.py +1 -0
  374. infrahub_sdk/task/constants.py +3 -0
  375. infrahub_sdk/task/exceptions.py +25 -0
  376. infrahub_sdk/task/manager.py +545 -0
  377. infrahub_sdk/task/models.py +74 -0
  378. infrahub_sdk/timestamp.py +134 -33
  379. infrahub_sdk/utils.py +39 -1
  380. infrahub_sdk/yaml.py +2 -3
  381. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/METADATA +47 -12
  382. infrahub_server-1.2.0b1.dist-info/RECORD +725 -0
  383. infrahub_testcontainers/container.py +14 -6
  384. infrahub_testcontainers/docker-compose.test.yml +24 -5
  385. infrahub_testcontainers/haproxy.cfg +43 -0
  386. infrahub_testcontainers/helpers.py +85 -1
  387. infrahub/core/branch/constants.py +0 -2
  388. infrahub/core/schema/definitions/core.py +0 -2274
  389. infrahub/graphql/query.py +0 -52
  390. infrahub/message_bus/messages/check_repository_checkdefinition.py +0 -20
  391. infrahub/message_bus/messages/check_repository_mergeconflicts.py +0 -16
  392. infrahub/message_bus/messages/check_repository_usercheck.py +0 -26
  393. infrahub/message_bus/messages/request_artifactdefinition_check.py +0 -17
  394. infrahub/message_bus/messages/request_repository_checks.py +0 -12
  395. infrahub/message_bus/messages/request_repository_userchecks.py +0 -18
  396. infrahub/message_bus/operations/check/repository.py +0 -293
  397. infrahub/message_bus/operations/requests/artifact_definition.py +0 -148
  398. infrahub/message_bus/operations/requests/repository.py +0 -133
  399. infrahub/schema/constants.py +0 -1
  400. infrahub/schema/tasks.py +0 -76
  401. infrahub/services/adapters/database/__init__.py +0 -9
  402. infrahub_sdk/ctl/_file.py +0 -13
  403. infrahub_server-1.1.6.dist-info/RECORD +0 -681
  404. /infrahub/{schema → artifacts}/__init__.py +0 -0
  405. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/LICENSE.txt +0 -0
  406. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/WHEEL +0 -0
  407. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/entry_points.txt +0 -0
@@ -9,6 +9,8 @@ from typing_extensions import Self
9
9
 
10
10
  from infrahub.core.branch import Branch
11
11
  from infrahub.database import retry_db_transaction
12
+ from infrahub.graphql.context import apply_external_context
13
+ from infrahub.graphql.types.context import ContextInput
12
14
  from infrahub.log import get_logger
13
15
  from infrahub.workflows.catalogue import (
14
16
  BRANCH_CREATE,
@@ -28,8 +30,6 @@ if TYPE_CHECKING:
28
30
  from ..initialization import GraphqlContext
29
31
 
30
32
 
31
- # pylint: disable=unused-argument
32
-
33
33
  log = get_logger()
34
34
 
35
35
 
@@ -46,6 +46,7 @@ class BranchCreateInput(InputObjectType):
46
46
  class BranchCreate(Mutation):
47
47
  class Arguments:
48
48
  data = BranchCreateInput(required=True)
49
+ context = ContextInput(required=False)
49
50
  background_execution = Boolean(required=False, deprecation_reason="Please use `wait_until_completion` instead")
50
51
  wait_until_completion = Boolean(required=False)
51
52
 
@@ -57,28 +58,32 @@ class BranchCreate(Mutation):
57
58
  @trace.get_tracer(__name__).start_as_current_span("branch_create")
58
59
  async def mutate(
59
60
  cls,
60
- root: dict,
61
+ root: dict, # noqa: ARG003
61
62
  info: GraphQLResolveInfo,
62
63
  data: BranchCreateInput,
64
+ context: ContextInput | None = None,
63
65
  background_execution: bool = False,
64
66
  wait_until_completion: bool = True,
65
67
  ) -> Self:
66
- context: GraphqlContext = info.context
68
+ graphql_context: GraphqlContext = info.context
67
69
  task: dict | None = None
68
70
 
69
71
  model = BranchCreateModel(**data)
72
+ await apply_external_context(graphql_context=graphql_context, context_input=context)
70
73
 
71
74
  if background_execution or not wait_until_completion:
72
- workflow = await context.active_service.workflow.submit_workflow(
73
- workflow=BRANCH_CREATE, parameters={"model": model}
75
+ workflow = await graphql_context.active_service.workflow.submit_workflow(
76
+ workflow=BRANCH_CREATE, context=graphql_context.get_context(), parameters={"model": model}
74
77
  )
75
78
  task = {"id": workflow.id}
76
79
  return cls(ok=True, task=task)
77
80
 
78
- await context.active_service.workflow.execute_workflow(workflow=BRANCH_CREATE, parameters={"model": model})
81
+ await graphql_context.active_service.workflow.execute_workflow(
82
+ workflow=BRANCH_CREATE, context=graphql_context.get_context(), parameters={"model": model}
83
+ )
79
84
 
80
85
  # Retrieve created branch
81
- obj = await Branch.get_by_name(db=context.db, name=model.name)
86
+ obj = await Branch.get_by_name(db=graphql_context.db, name=model.name)
82
87
  fields = await extract_fields(info.field_nodes[0].selection_set)
83
88
  return cls(object=await obj.to_graphql(fields=fields.get("object", {})), ok=True, task=task)
84
89
 
@@ -96,6 +101,7 @@ class BranchUpdateInput(InputObjectType):
96
101
  class BranchDelete(Mutation):
97
102
  class Arguments:
98
103
  data = BranchNameInput(required=True)
104
+ context = ContextInput(required=False)
99
105
  wait_until_completion = Boolean(required=False)
100
106
 
101
107
  ok = Boolean()
@@ -103,19 +109,25 @@ class BranchDelete(Mutation):
103
109
 
104
110
  @classmethod
105
111
  async def mutate(
106
- cls, root: dict, info: GraphQLResolveInfo, data: BranchNameInput, wait_until_completion: bool = True
112
+ cls,
113
+ root: dict, # noqa: ARG003
114
+ info: GraphQLResolveInfo,
115
+ data: BranchNameInput,
116
+ context: ContextInput | None = None,
117
+ wait_until_completion: bool = True,
107
118
  ) -> Self:
108
- context: GraphqlContext = info.context
109
- obj = await Branch.get_by_name(db=context.db, name=str(data.name))
119
+ graphql_context: GraphqlContext = info.context
120
+ obj = await Branch.get_by_name(db=graphql_context.db, name=str(data.name))
121
+ await apply_external_context(graphql_context=graphql_context, context_input=context)
110
122
 
111
123
  if wait_until_completion:
112
- await context.active_service.workflow.execute_workflow(
113
- workflow=BRANCH_DELETE, parameters={"branch": obj.name}
124
+ await graphql_context.active_service.workflow.execute_workflow(
125
+ workflow=BRANCH_DELETE, context=graphql_context.get_context(), parameters={"branch": obj.name}
114
126
  )
115
127
  return cls(ok=True)
116
128
 
117
- workflow = await context.active_service.workflow.submit_workflow(
118
- workflow=BRANCH_DELETE, parameters={"branch": obj.name}
129
+ workflow = await graphql_context.active_service.workflow.submit_workflow(
130
+ workflow=BRANCH_DELETE, context=graphql_context.get_context(), parameters={"branch": obj.name}
119
131
  )
120
132
  return cls(ok=True, task={"id": str(workflow.id)})
121
133
 
@@ -123,22 +135,30 @@ class BranchDelete(Mutation):
123
135
  class BranchUpdate(Mutation):
124
136
  class Arguments:
125
137
  data = BranchUpdateInput(required=True)
138
+ context = ContextInput(required=False)
126
139
 
127
140
  ok = Boolean()
128
141
 
129
142
  @classmethod
130
143
  @retry_db_transaction(name="branch_update")
131
- async def mutate(cls, root: dict, info: GraphQLResolveInfo, data: BranchNameInput) -> Self:
132
- context: GraphqlContext = info.context
144
+ async def mutate(
145
+ cls,
146
+ root: dict, # noqa: ARG003
147
+ info: GraphQLResolveInfo,
148
+ data: BranchNameInput,
149
+ context: ContextInput | None = None,
150
+ ) -> Self:
151
+ graphql_context: GraphqlContext = info.context
133
152
 
134
- obj = await Branch.get_by_name(db=context.db, name=data["name"])
153
+ obj = await Branch.get_by_name(db=graphql_context.db, name=data["name"])
154
+ await apply_external_context(graphql_context=graphql_context, context_input=context)
135
155
 
136
156
  to_extract = ["description"]
137
157
  for field_name in to_extract:
138
158
  if field_name in data and data.get(field_name) is not None:
139
159
  setattr(obj, field_name, data[field_name])
140
160
 
141
- async with context.db.start_transaction() as db:
161
+ async with graphql_context.db.start_transaction() as db:
142
162
  await obj.save(db=db)
143
163
 
144
164
  return cls(ok=True)
@@ -147,6 +167,7 @@ class BranchUpdate(Mutation):
147
167
  class BranchRebase(Mutation):
148
168
  class Arguments:
149
169
  data = BranchNameInput(required=True)
170
+ context = ContextInput(required=False)
150
171
  wait_until_completion = Boolean(required=False)
151
172
 
152
173
  ok = Boolean()
@@ -155,23 +176,29 @@ class BranchRebase(Mutation):
155
176
 
156
177
  @classmethod
157
178
  async def mutate(
158
- cls, root: dict, info: GraphQLResolveInfo, data: BranchNameInput, wait_until_completion: bool = True
179
+ cls,
180
+ root: dict, # noqa: ARG003
181
+ info: GraphQLResolveInfo,
182
+ data: BranchNameInput,
183
+ context: ContextInput | None = None,
184
+ wait_until_completion: bool = True,
159
185
  ) -> Self:
160
- context: GraphqlContext = info.context
186
+ graphql_context: GraphqlContext = info.context
161
187
 
162
- obj = await Branch.get_by_name(db=context.db, name=str(data.name))
188
+ obj = await Branch.get_by_name(db=graphql_context.db, name=str(data.name))
189
+ await apply_external_context(graphql_context=graphql_context, context_input=context)
163
190
  task: dict | None = None
164
191
 
165
192
  if wait_until_completion:
166
- await context.active_service.workflow.execute_workflow(
167
- workflow=BRANCH_REBASE, parameters={"branch": obj.name}
193
+ await graphql_context.active_service.workflow.execute_workflow(
194
+ workflow=BRANCH_REBASE, context=graphql_context.get_context(), parameters={"branch": obj.name}
168
195
  )
169
196
 
170
197
  # Pull the latest information about the branch from the database directly
171
- obj = await Branch.get_by_name(db=context.db, name=str(data.name))
198
+ obj = await Branch.get_by_name(db=graphql_context.db, name=str(data.name))
172
199
  else:
173
- workflow = await context.active_service.workflow.submit_workflow(
174
- workflow=BRANCH_REBASE, parameters={"branch": obj.name}
200
+ workflow = await graphql_context.active_service.workflow.submit_workflow(
201
+ workflow=BRANCH_REBASE, context=graphql_context.get_context(), parameters={"branch": obj.name}
175
202
  )
176
203
  task = {"id": workflow.id}
177
204
 
@@ -184,6 +211,7 @@ class BranchRebase(Mutation):
184
211
  class BranchValidate(Mutation):
185
212
  class Arguments:
186
213
  data = BranchNameInput(required=True)
214
+ context = ContextInput(required=False)
187
215
  wait_until_completion = Boolean(required=False)
188
216
 
189
217
  ok = Boolean()
@@ -193,21 +221,27 @@ class BranchValidate(Mutation):
193
221
  @classmethod
194
222
  @retry_db_transaction(name="branch_validate")
195
223
  async def mutate(
196
- cls, root: dict, info: GraphQLResolveInfo, data: BranchNameInput, wait_until_completion: bool = True
224
+ cls,
225
+ root: dict, # noqa: ARG003
226
+ info: GraphQLResolveInfo,
227
+ data: BranchNameInput,
228
+ context: ContextInput | None = None,
229
+ wait_until_completion: bool = True,
197
230
  ) -> Self:
198
- context: GraphqlContext = info.context
231
+ graphql_context: GraphqlContext = info.context
199
232
 
200
- obj = await Branch.get_by_name(db=context.db, name=str(data.name))
233
+ obj = await Branch.get_by_name(db=graphql_context.db, name=str(data.name))
234
+ await apply_external_context(graphql_context=graphql_context, context_input=context)
201
235
  task: dict | None = None
202
236
  ok = True
203
237
 
204
238
  if wait_until_completion:
205
- await context.active_service.workflow.execute_workflow(
206
- workflow=BRANCH_VALIDATE, parameters={"branch": obj.name}
239
+ await graphql_context.active_service.workflow.execute_workflow(
240
+ workflow=BRANCH_VALIDATE, context=graphql_context.get_context(), parameters={"branch": obj.name}
207
241
  )
208
242
  else:
209
- workflow = await context.active_service.workflow.submit_workflow(
210
- workflow=BRANCH_VALIDATE, parameters={"branch": obj.name}
243
+ workflow = await graphql_context.active_service.workflow.submit_workflow(
244
+ workflow=BRANCH_VALIDATE, context=graphql_context.get_context(), parameters={"branch": obj.name}
211
245
  )
212
246
  task = {"id": workflow.id}
213
247
 
@@ -219,6 +253,7 @@ class BranchValidate(Mutation):
219
253
  class BranchMerge(Mutation):
220
254
  class Arguments:
221
255
  data = BranchNameInput(required=True)
256
+ context = ContextInput(required=False)
222
257
  wait_until_completion = Boolean(required=False)
223
258
 
224
259
  ok = Boolean()
@@ -227,23 +262,34 @@ class BranchMerge(Mutation):
227
262
 
228
263
  @classmethod
229
264
  async def mutate(
230
- cls, root: dict, info: GraphQLResolveInfo, data: BranchNameInput, wait_until_completion: bool = True
265
+ cls,
266
+ root: dict, # noqa: ARG003
267
+ info: GraphQLResolveInfo,
268
+ data: BranchNameInput,
269
+ context: ContextInput | None = None,
270
+ wait_until_completion: bool = True,
231
271
  ) -> Self:
232
272
  branch_name = data["name"]
233
273
  task: dict | None = None
274
+ graphql_context: GraphqlContext = info.context
275
+ await apply_external_context(graphql_context=graphql_context, context_input=context)
234
276
 
235
277
  if wait_until_completion:
236
- await info.context.active_service.workflow.execute_workflow(
237
- workflow=BRANCH_MERGE_MUTATION, parameters={"branch": branch_name}
278
+ await graphql_context.active_service.workflow.execute_workflow(
279
+ workflow=BRANCH_MERGE_MUTATION,
280
+ context=graphql_context.get_context(),
281
+ parameters={"branch": branch_name},
238
282
  )
239
283
  else:
240
- workflow = await info.context.active_service.workflow.submit_workflow(
241
- workflow=BRANCH_MERGE_MUTATION, parameters={"branch": branch_name}
284
+ workflow = await graphql_context.active_service.workflow.submit_workflow(
285
+ workflow=BRANCH_MERGE_MUTATION,
286
+ context=graphql_context.get_context(),
287
+ parameters={"branch": branch_name},
242
288
  )
243
289
  task = {"id": workflow.id}
244
290
 
245
291
  # Pull the latest information about the branch from the database directly
246
- obj = await Branch.get_by_name(db=info.context.db, name=branch_name)
292
+ obj = await Branch.get_by_name(db=graphql_context.db, name=branch_name)
247
293
 
248
294
  fields = await extract_fields(info.field_nodes[0].selection_set)
249
295
  ok = True
@@ -9,8 +9,11 @@ from infrahub.core.constants import ComputedAttributeKind, MutationAction, Permi
9
9
  from infrahub.core.manager import NodeManager
10
10
  from infrahub.core.registry import registry
11
11
  from infrahub.database import retry_db_transaction
12
- from infrahub.events import EventMeta, NodeMutatedEvent
12
+ from infrahub.events import EventMeta
13
+ from infrahub.events.node_action import NodeMutatedEvent
13
14
  from infrahub.exceptions import NodeNotFoundError, ValidationError
15
+ from infrahub.graphql.context import apply_external_context
16
+ from infrahub.graphql.types.context import ContextInput
14
17
  from infrahub.log import get_log_data
15
18
  from infrahub.worker import WORKER_IDENTITY
16
19
 
@@ -30,6 +33,7 @@ class InfrahubComputedAttributeUpdateInput(InputObjectType):
30
33
  class UpdateComputedAttribute(Mutation):
31
34
  class Arguments:
32
35
  data = InfrahubComputedAttributeUpdateInput(required=True)
36
+ context = ContextInput(required=False)
33
37
 
34
38
  ok = Boolean()
35
39
 
@@ -40,9 +44,12 @@ class UpdateComputedAttribute(Mutation):
40
44
  _: dict,
41
45
  info: GraphQLResolveInfo,
42
46
  data: InfrahubComputedAttributeUpdateInput,
47
+ context: ContextInput | None = None,
43
48
  ) -> UpdateComputedAttribute:
44
- context: GraphqlContext = info.context
45
- node_schema = registry.schema.get_node_schema(name=str(data.kind), branch=context.branch.name, duplicate=False)
49
+ graphql_context: GraphqlContext = info.context
50
+ node_schema = registry.schema.get_node_schema(
51
+ name=str(data.kind), branch=graphql_context.branch.name, duplicate=False
52
+ )
46
53
  target_attribute = node_schema.get_attribute(name=str(data.attribute))
47
54
  if (
48
55
  not target_attribute.computed_attribute
@@ -50,20 +57,21 @@ class UpdateComputedAttribute(Mutation):
50
57
  ):
51
58
  raise ValidationError(input_value=f"{node_schema.kind}.{target_attribute.name} is not a computed attribute")
52
59
 
53
- context.active_permissions.raise_for_permission(
60
+ graphql_context.active_permissions.raise_for_permission(
54
61
  permission=ObjectPermission(
55
62
  namespace=node_schema.namespace,
56
63
  name=node_schema.name,
57
64
  action=PermissionAction.UPDATE.value,
58
65
  decision=PermissionDecision.ALLOW_DEFAULT.value
59
- if context.branch.name == registry.default_branch
66
+ if graphql_context.branch.name == registry.default_branch
60
67
  else PermissionDecision.ALLOW_OTHER.value,
61
68
  )
62
69
  )
70
+ await apply_external_context(graphql_context=graphql_context, context_input=context)
63
71
 
64
72
  if not (
65
73
  target_node := await NodeManager.get_one(
66
- db=context.db, kind=node_schema.kind, id=str(data.id), branch=context.branch
74
+ db=graphql_context.db, kind=node_schema.kind, id=str(data.id), branch=graphql_context.branch
67
75
  )
68
76
  ):
69
77
  raise NodeNotFoundError(
@@ -81,24 +89,27 @@ class UpdateComputedAttribute(Mutation):
81
89
  )
82
90
  if attribute_field.value != str(data.value):
83
91
  attribute_field.value = str(data.value)
84
- async with context.db.start_transaction() as dbt:
92
+ async with graphql_context.db.start_transaction() as dbt:
85
93
  await target_node.save(db=dbt, fields=[str(data.attribute)])
86
94
 
87
95
  log_data = get_log_data()
88
96
  request_id = log_data.get("request_id", "")
89
97
 
90
- graphql_payload = await target_node.to_graphql(db=context.db, filter_sensitive=True)
91
-
92
98
  event = NodeMutatedEvent(
93
- branch=context.branch.name,
94
99
  kind=node_schema.kind,
95
100
  node_id=target_node.get_id(),
96
- data=graphql_payload,
101
+ data=target_node.node_changelog.model_dump(),
97
102
  fields=[str(data.attribute)],
98
103
  action=MutationAction.UPDATED,
99
- meta=EventMeta(initiator_id=WORKER_IDENTITY, request_id=request_id),
104
+ meta=EventMeta(
105
+ context=graphql_context.get_context(),
106
+ initiator_id=WORKER_IDENTITY,
107
+ request_id=request_id,
108
+ account_id=graphql_context.active_account_session.account_id,
109
+ branch=graphql_context.branch,
110
+ ),
100
111
  )
101
- await context.active_service.event.send(event=event)
112
+ await graphql_context.active_service.event.send(event=event)
102
113
 
103
114
  result: dict[str, Any] = {"ok": True}
104
115
 
@@ -1,15 +1,22 @@
1
1
  from typing import TYPE_CHECKING
2
2
 
3
- from graphene import Boolean, DateTime, InputObjectType, Mutation, String
3
+ from graphene import Boolean, DateTime, Field, InputObjectType, Mutation, String
4
4
  from graphql import GraphQLResolveInfo
5
5
 
6
6
  from infrahub.core import registry
7
7
  from infrahub.core.diff.coordinator import DiffCoordinator
8
+ from infrahub.core.diff.model.path import NameTrackingId
8
9
  from infrahub.core.diff.models import RequestDiffUpdate
9
- from infrahub.database import retry_db_transaction
10
+ from infrahub.core.diff.repository.repository import DiffRepository
11
+ from infrahub.core.timestamp import Timestamp
10
12
  from infrahub.dependencies.registry import get_component_registry
13
+ from infrahub.exceptions import ValidationError
14
+ from infrahub.graphql.context import apply_external_context
15
+ from infrahub.graphql.types.context import ContextInput
11
16
  from infrahub.workflows.catalogue import DIFF_UPDATE
12
17
 
18
+ from ..types.task import TaskInfo
19
+
13
20
  if TYPE_CHECKING:
14
21
  from ..initialization import GraphqlContext
15
22
 
@@ -19,34 +26,64 @@ class DiffUpdateInput(InputObjectType):
19
26
  name = String(required=False)
20
27
  from_time = DateTime(required=False)
21
28
  to_time = DateTime(required=False)
22
- wait_for_completion = Boolean(required=False)
29
+ wait_for_completion = Boolean(required=False, deprecation_reason="Please use `wait_until_completion` instead")
23
30
 
24
31
 
25
32
  class DiffUpdateMutation(Mutation):
26
33
  class Arguments:
27
34
  data = DiffUpdateInput(required=True)
35
+ context = ContextInput(required=False)
36
+ wait_until_completion = Boolean(required=False)
28
37
 
29
38
  ok = Boolean()
39
+ task = Field(TaskInfo, required=False)
30
40
 
31
41
  @classmethod
32
- @retry_db_transaction(name="diff_update")
33
42
  async def mutate(
34
43
  cls,
35
- root: dict, # pylint: disable=unused-argument
44
+ root: dict, # noqa: ARG003
36
45
  info: GraphQLResolveInfo,
37
46
  data: DiffUpdateInput,
38
- ) -> dict[str, bool]:
39
- context: GraphqlContext = info.context
47
+ context: ContextInput | None = None,
48
+ wait_until_completion: bool = False,
49
+ ) -> dict[str, bool | dict[str, str]]:
50
+ graphql_context: GraphqlContext = info.context
51
+ await apply_external_context(graphql_context=graphql_context, context_input=context)
52
+
53
+ if data.wait_for_completion is True:
54
+ wait_until_completion = True
40
55
 
41
56
  from_timestamp_str = DateTime.serialize(data.from_time) if data.from_time else None
42
57
  to_timestamp_str = DateTime.serialize(data.to_time) if data.to_time else None
43
- if data.wait_for_completion is True:
44
- component_registry = get_component_registry()
45
- base_branch = await registry.get_branch(db=context.db, branch=registry.default_branch)
46
- diff_branch = await registry.get_branch(db=context.db, branch=data.branch)
58
+ if (data.from_time or data.to_time) and not data.name:
59
+ raise ValidationError("diff with specified time range requires a name")
47
60
 
61
+ component_registry = get_component_registry()
62
+ base_branch = await registry.get_branch(db=graphql_context.db, branch=registry.default_branch)
63
+ diff_branch = await registry.get_branch(db=graphql_context.db, branch=data.branch)
64
+ diff_repository = await component_registry.get_component(
65
+ DiffRepository, db=graphql_context.db, branch=diff_branch
66
+ )
67
+
68
+ tracking_id = NameTrackingId(name=data.name)
69
+ existing_diffs_metadatas = await diff_repository.get_roots_metadata(
70
+ diff_branch_names=[diff_branch.name], base_branch_names=[base_branch.name], tracking_id=tracking_id
71
+ )
72
+ if existing_diffs_metadatas:
73
+ metadata = existing_diffs_metadatas[0]
74
+ from_time = Timestamp(from_timestamp_str) if from_timestamp_str else None
75
+ to_time = Timestamp(to_timestamp_str) if to_timestamp_str else None
76
+ branched_from_timestamp = Timestamp(diff_branch.get_branched_from())
77
+ if from_time and from_time > metadata.from_time:
78
+ raise ValidationError(f"from_time must be null or less than or equal to {metadata.from_time}")
79
+ if from_time and from_time < branched_from_timestamp:
80
+ raise ValidationError(f"from_time must be null or greater than or equal to {branched_from_timestamp}")
81
+ if to_time and to_time < metadata.to_time:
82
+ raise ValidationError(f"to_time must be null or greater than or equal to {metadata.to_time}")
83
+
84
+ if wait_until_completion is True:
48
85
  diff_coordinator = await component_registry.get_component(
49
- DiffCoordinator, db=context.db, branch=diff_branch
86
+ DiffCoordinator, db=graphql_context.db, branch=diff_branch
50
87
  )
51
88
  await diff_coordinator.run_update(
52
89
  base_branch=base_branch,
@@ -64,7 +101,10 @@ class DiffUpdateMutation(Mutation):
64
101
  from_time=from_timestamp_str,
65
102
  to_time=to_timestamp_str,
66
103
  )
67
- if context.service:
68
- await context.service.workflow.submit_workflow(workflow=DIFF_UPDATE, parameters={"model": model})
104
+ if graphql_context.service:
105
+ workflow = await graphql_context.service.workflow.submit_workflow(
106
+ workflow=DIFF_UPDATE, parameters={"model": model}
107
+ )
108
+ return {"ok": True, "task": {"id": str(workflow.id)}}
69
109
 
70
110
  return {"ok": True}
@@ -11,7 +11,9 @@ from infrahub.core.manager import NodeManager
11
11
  from infrahub.database import retry_db_transaction
12
12
  from infrahub.dependencies.registry import get_component_registry
13
13
  from infrahub.exceptions import ProcessingError
14
+ from infrahub.graphql.context import apply_external_context
14
15
  from infrahub.graphql.enums import ConflictSelection as GraphQlConflictSelection
16
+ from infrahub.graphql.types.context import ContextInput
15
17
 
16
18
  if TYPE_CHECKING:
17
19
  from graphql import GraphQLResolveInfo
@@ -19,9 +21,6 @@ if TYPE_CHECKING:
19
21
  from ..initialization import GraphqlContext
20
22
 
21
23
 
22
- # pylint: disable=unused-argument
23
-
24
-
25
24
  class ResolveDiffConflictInput(InputObjectType):
26
25
  conflict_id = InputField(String(required=True), description="ID of the diff conflict to resolve")
27
26
  selected_branch = InputField(
@@ -32,6 +31,7 @@ class ResolveDiffConflictInput(InputObjectType):
32
31
  class ResolveDiffConflict(Mutation):
33
32
  class Arguments:
34
33
  data = ResolveDiffConflictInput(required=True)
34
+ context = ContextInput(required=False)
35
35
 
36
36
  ok = Boolean()
37
37
 
@@ -39,14 +39,18 @@ class ResolveDiffConflict(Mutation):
39
39
  @retry_db_transaction(name="resolve_diff_conflict")
40
40
  async def mutate(
41
41
  cls,
42
- root: dict,
42
+ root: dict, # noqa: ARG003
43
43
  info: GraphQLResolveInfo,
44
44
  data: ResolveDiffConflictInput,
45
+ context: ContextInput | None = None,
45
46
  ) -> ResolveDiffConflict:
46
- context: GraphqlContext = info.context
47
+ graphql_context: GraphqlContext = info.context
48
+ await apply_external_context(graphql_context=graphql_context, context_input=context)
47
49
 
48
50
  component_registry = get_component_registry()
49
- diff_repo = await component_registry.get_component(DiffRepository, db=context.db, branch=context.branch)
51
+ diff_repo = await component_registry.get_component(
52
+ DiffRepository, db=graphql_context.db, branch=graphql_context.branch
53
+ )
50
54
 
51
55
  selection = ConflictSelection(data.selected_branch.value) if data.selected_branch else None
52
56
  conflict = await diff_repo.get_conflict_by_id(conflict_id=data.conflict_id)
@@ -55,7 +59,9 @@ class ResolveDiffConflict(Mutation):
55
59
  await diff_repo.update_conflict_by_id(conflict_id=data.conflict_id, selection=selection)
56
60
 
57
61
  core_data_checks = await NodeManager.query(
58
- db=context.db, schema=InfrahubKind.DATACHECK, filters={"enriched_conflict_id__value": data.conflict_id}
62
+ db=graphql_context.db,
63
+ schema=InfrahubKind.DATACHECK,
64
+ filters={"enriched_conflict_id__value": data.conflict_id},
59
65
  )
60
66
  if not core_data_checks:
61
67
  return cls(ok=True)
@@ -67,5 +73,5 @@ class ResolveDiffConflict(Mutation):
67
73
  keep_branch = None
68
74
  for cdc in core_data_checks:
69
75
  cdc.keep_branch.value = keep_branch
70
- await cdc.save(db=context.db)
76
+ await cdc.save(db=graphql_context.db)
71
77
  return cls(ok=True)
@@ -0,0 +1,83 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from graphene import Boolean, Field, InputField, InputObjectType, List, Mutation, NonNull, String
6
+
7
+ from infrahub.core.manager import NodeManager
8
+ from infrahub.generators.models import ProposedChangeGeneratorDefinition, RequestGeneratorDefinitionRun
9
+ from infrahub.graphql.context import apply_external_context
10
+ from infrahub.graphql.types.context import ContextInput
11
+ from infrahub.graphql.types.task import TaskInfo
12
+ from infrahub.workflows.catalogue import REQUEST_GENERATOR_DEFINITION_RUN
13
+
14
+ if TYPE_CHECKING:
15
+ from graphql import GraphQLResolveInfo
16
+
17
+ from ..initialization import GraphqlContext
18
+
19
+
20
+ class GeneratorDefinitionRequestRunInput(InputObjectType):
21
+ id = InputField(String(required=True), description="ID of the generator definition to run")
22
+ nodes = InputField(List(of_type=NonNull(String)), description="ID list of targets to run the generator for")
23
+
24
+
25
+ class GeneratorDefinitionRequestRun(Mutation):
26
+ class Arguments:
27
+ data = GeneratorDefinitionRequestRunInput(required=True)
28
+ context = ContextInput(required=False)
29
+ wait_until_completion = Boolean(required=False)
30
+
31
+ ok = Boolean()
32
+ task = Field(TaskInfo, required=False)
33
+
34
+ @classmethod
35
+ async def mutate(
36
+ cls,
37
+ root: dict, # noqa: ARG003
38
+ info: GraphQLResolveInfo,
39
+ data: GeneratorDefinitionRequestRunInput,
40
+ context: ContextInput | None = None,
41
+ wait_until_completion: bool = True,
42
+ ) -> GeneratorDefinitionRequestRun:
43
+ graphql_context: GraphqlContext = info.context
44
+ db = graphql_context.db
45
+ await apply_external_context(graphql_context=graphql_context, context_input=context)
46
+ generator_definition = await NodeManager.get_one(
47
+ id=str(data.id), db=db, branch=graphql_context.branch, prefetch_relationships=True, raise_on_error=True
48
+ )
49
+ query = await generator_definition.query.get_peer(db=db)
50
+ repository = await generator_definition.repository.get_peer(db=db)
51
+ group = await generator_definition.targets.get_peer(db=db)
52
+
53
+ request_model = RequestGeneratorDefinitionRun(
54
+ generator_definition=ProposedChangeGeneratorDefinition(
55
+ definition_id=generator_definition.id,
56
+ definition_name=generator_definition.name.value,
57
+ class_name=generator_definition.class_name.value,
58
+ file_path=generator_definition.file_path.value,
59
+ query_name=query.name.value,
60
+ query_models=query.models.value,
61
+ repository_id=repository.id,
62
+ parameters=generator_definition.parameters.value,
63
+ group_id=group.id,
64
+ convert_query_response=generator_definition.convert_query_response.value or False,
65
+ ),
66
+ branch=graphql_context.branch.name,
67
+ target_members=data.get("nodes", []),
68
+ )
69
+
70
+ if not wait_until_completion:
71
+ workflow = await graphql_context.active_service.workflow.submit_workflow(
72
+ workflow=REQUEST_GENERATOR_DEFINITION_RUN,
73
+ context=graphql_context.get_context(),
74
+ parameters={"model": request_model},
75
+ )
76
+ return cls(ok=True, task={"id": workflow.id})
77
+
78
+ await graphql_context.active_service.workflow.execute_workflow(
79
+ workflow=REQUEST_GENERATOR_DEFINITION_RUN,
80
+ context=graphql_context.get_context(),
81
+ parameters={"model": request_model},
82
+ )
83
+ return cls(ok=True)