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
@@ -11,23 +11,16 @@ if TYPE_CHECKING:
11
11
  from infrahub.graphql.initialization import GraphqlContext
12
12
 
13
13
 
14
- async def get_permissions(schema: MainSchemaTypes, context: GraphqlContext) -> dict[str, Any]:
14
+ async def get_permissions(schema: MainSchemaTypes, graphql_context: GraphqlContext) -> dict[str, Any]:
15
15
  schema_objects = [schema]
16
16
  if isinstance(schema, GenericSchema):
17
17
  for node_name in schema.used_by:
18
- schema_object: MainSchemaTypes
19
- try:
20
- schema_object = registry.schema.get_node_schema(name=node_name, branch=context.branch, duplicate=False)
21
- except ValueError:
22
- schema_object = registry.schema.get_profile_schema(
23
- name=node_name, branch=context.branch, duplicate=False
24
- )
25
- schema_objects.append(schema_object)
18
+ schema_objects.append(registry.schema.get(name=node_name, branch=graphql_context.branch, duplicate=False))
26
19
 
27
20
  response: dict[str, Any] = {"count": len(schema_objects), "edges": []}
28
21
 
29
22
  nodes = await report_schema_permissions(
30
- branch=context.branch, permission_manager=context.active_permissions, schemas=schema_objects
23
+ branch=graphql_context.branch, permission_manager=graphql_context.active_permissions, schemas=schema_objects
31
24
  )
32
25
  response["edges"] = [{"node": node} for node in nodes]
33
26
 
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING, Any
4
4
 
5
- from graphene import Field, Int, List, ObjectType, String
5
+ from graphene import Field, Int, List, NonNull, ObjectType, String
6
6
  from infrahub_sdk.utils import extract_fields_first_node
7
7
 
8
8
  from infrahub.core.manager import NodeManager
@@ -27,32 +27,32 @@ class AccountTokenEdge(ObjectType):
27
27
 
28
28
  class AccountTokenEdges(ObjectType):
29
29
  count = Field(Int, required=True)
30
- edges = Field(List(of_type=AccountTokenEdge, required=True), required=True)
30
+ edges = Field(List(of_type=NonNull(AccountTokenEdge), required=True), required=True)
31
31
 
32
32
 
33
33
  async def resolve_account_tokens(
34
- root: dict, # pylint: disable=unused-argument
34
+ root: dict, # noqa: ARG001
35
35
  info: GraphQLResolveInfo,
36
36
  limit: int = 10,
37
37
  offset: int = 0,
38
38
  ) -> dict:
39
- context: GraphqlContext = info.context
39
+ graphql_context: GraphqlContext = info.context
40
40
 
41
- if not context.account_session:
41
+ if not graphql_context.account_session:
42
42
  raise ValueError("An account_session is mandatory to execute this query")
43
43
 
44
- if not context.account_session.authenticated_by_jwt:
44
+ if not graphql_context.account_session.authenticated_by_jwt:
45
45
  raise PermissionDeniedError("This operation requires authentication with a JWT token")
46
46
 
47
47
  fields = await extract_fields_first_node(info)
48
48
 
49
- filters = {"account__ids": [context.account_session.account_id]}
49
+ filters = {"account__ids": [graphql_context.account_session.account_id]}
50
50
  response: dict[str, Any] = {}
51
51
  if "count" in fields:
52
- response["count"] = await NodeManager.count(db=context.db, schema=InternalAccountToken, filters=filters)
52
+ response["count"] = await NodeManager.count(db=graphql_context.db, schema=InternalAccountToken, filters=filters)
53
53
  if "edges" in fields:
54
54
  objs = await NodeManager.query(
55
- db=context.db, schema=InternalAccountToken, filters=filters, limit=limit, offset=offset
55
+ db=graphql_context.db, schema=InternalAccountToken, filters=filters, limit=limit, offset=offset
56
56
  )
57
57
  response["edges"] = [
58
58
  {"node": {"id": obj.id, "name": obj.name.value, "expiration": obj.expiration.value}} for obj in objs
@@ -62,7 +62,11 @@ async def resolve_account_tokens(
62
62
 
63
63
 
64
64
  AccountToken = Field(
65
- AccountTokenEdges, resolver=resolve_account_tokens, limit=Int(required=False), offset=Int(required=False)
65
+ AccountTokenEdges,
66
+ limit=Int(required=False),
67
+ offset=Int(required=False),
68
+ resolver=resolve_account_tokens,
69
+ required=True,
66
70
  )
67
71
 
68
72
 
@@ -95,12 +99,12 @@ class AccountObjectPermissionEdge(ObjectType):
95
99
 
96
100
  class AccountGlobalPermissionEdges(ObjectType):
97
101
  count = Field(Int, required=True)
98
- edges = Field(List(of_type=AccountGlobalPermissionEdge, required=True), required=True)
102
+ edges = Field(List(of_type=NonNull(AccountGlobalPermissionEdge), required=True), required=True)
99
103
 
100
104
 
101
105
  class AccountObjectPermissionEdges(ObjectType):
102
106
  count = Field(Int, required=True)
103
- edges = Field(List(of_type=AccountObjectPermissionEdge, required=True), required=True)
107
+ edges = Field(List(of_type=NonNull(AccountObjectPermissionEdge), required=True), required=True)
104
108
 
105
109
 
106
110
  class AccountPermissionsEdges(ObjectType):
@@ -109,19 +113,19 @@ class AccountPermissionsEdges(ObjectType):
109
113
 
110
114
 
111
115
  async def resolve_account_permissions(
112
- root: dict, # pylint: disable=unused-argument
116
+ root: dict, # noqa: ARG001
113
117
  info: GraphQLResolveInfo,
114
118
  ) -> dict:
115
- context: GraphqlContext = info.context
119
+ graphql_context: GraphqlContext = info.context
116
120
 
117
- if not context.account_session:
121
+ if not graphql_context.account_session:
118
122
  raise ValueError("An account_session is mandatory to execute this query")
119
123
 
120
124
  fields = await extract_fields_first_node(info)
121
125
 
122
126
  response: dict[str, dict[str, Any]] = {}
123
127
  if "global_permissions" in fields:
124
- global_list = context.active_permissions.permissions["global_permissions"]
128
+ global_list = graphql_context.active_permissions.permissions["global_permissions"]
125
129
  response["global_permissions"] = {"count": len(global_list)}
126
130
  response["global_permissions"]["edges"] = [
127
131
  {
@@ -136,7 +140,7 @@ async def resolve_account_permissions(
136
140
  for obj in global_list
137
141
  ]
138
142
  if "object_permissions" in fields:
139
- object_list = context.active_permissions.permissions["object_permissions"]
143
+ object_list = graphql_context.active_permissions.permissions["object_permissions"]
140
144
  response["object_permissions"] = {"count": len(object_list)}
141
145
  response["object_permissions"]["edges"] = [
142
146
  {
@@ -155,4 +159,4 @@ async def resolve_account_permissions(
155
159
  return response
156
160
 
157
161
 
158
- AccountPermissions = Field(AccountPermissionsEdges, resolver=resolve_account_permissions)
162
+ AccountPermissions = Field(AccountPermissionsEdges, resolver=resolve_account_permissions, required=True)
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING, Any
4
4
 
5
- from graphene import ID, Field, List, String
5
+ from graphene import ID, Field, List, NonNull, String
6
6
  from infrahub_sdk.utils import extract_fields_first_node
7
7
 
8
8
  from infrahub.graphql.types import BranchType
@@ -12,17 +12,19 @@ if TYPE_CHECKING:
12
12
 
13
13
 
14
14
  async def branch_resolver(
15
- root: dict, # pylint: disable=unused-argument
15
+ root: dict, # noqa: ARG001
16
16
  info: GraphQLResolveInfo,
17
17
  **kwargs: Any,
18
18
  ) -> list[dict[str, Any]]:
19
19
  fields = await extract_fields_first_node(info)
20
- return await BranchType.get_list(context=info.context, fields=fields, **kwargs)
20
+ return await BranchType.get_list(graphql_context=info.context, fields=fields, **kwargs)
21
21
 
22
22
 
23
23
  BranchQueryList = Field(
24
- List(BranchType),
24
+ List(of_type=NonNull(BranchType)),
25
25
  ids=List(ID),
26
26
  name=String(),
27
+ description="Retrieve information about active branches.",
27
28
  resolver=branch_resolver,
29
+ required=True,
28
30
  )
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING, Any, Optional, Union
4
4
 
5
- from graphene import Argument, Boolean, DateTime, Field, InputObjectType, Int, List, ObjectType, String
5
+ from graphene import Argument, Boolean, DateTime, Field, InputObjectType, Int, List, NonNull, ObjectType, String
6
6
  from graphene import Enum as GrapheneEnum
7
7
  from infrahub_sdk.utils import extract_fields
8
8
 
@@ -75,7 +75,7 @@ class DiffAttribute(DiffSummaryCounts):
75
75
  last_changed_at = DateTime(required=True)
76
76
  status = Field(GrapheneDiffActionEnum, required=True)
77
77
  path_identifier = String(required=True)
78
- properties = List(DiffProperty)
78
+ properties = List(NonNull(DiffProperty))
79
79
  contains_conflict = Boolean(required=True)
80
80
  conflict = Field(ConflictDetails, required=False)
81
81
 
@@ -88,7 +88,7 @@ class DiffSingleRelationship(DiffSummaryCounts):
88
88
  path_identifier = String(required=True)
89
89
  contains_conflict = Boolean(required=True)
90
90
  conflict = Field(ConflictDetails, required=False)
91
- properties = List(DiffProperty)
91
+ properties = List(NonNull(DiffProperty))
92
92
 
93
93
 
94
94
  class DiffRelationship(DiffSummaryCounts):
@@ -98,7 +98,7 @@ class DiffRelationship(DiffSummaryCounts):
98
98
  cardinality = Field(GrapheneCardinalityEnum, required=True)
99
99
  status = Field(GrapheneDiffActionEnum, required=True)
100
100
  path_identifier = String(required=True)
101
- elements = List(DiffSingleRelationship, required=True)
101
+ elements = List(NonNull(DiffSingleRelationship), required=True)
102
102
  contains_conflict = Boolean(required=True)
103
103
 
104
104
 
@@ -118,8 +118,8 @@ class DiffNode(DiffSummaryCounts):
118
118
  contains_conflict = Boolean(required=True)
119
119
  last_changed_at = DateTime(required=False)
120
120
  parent = Field(DiffNodeParent, required=False)
121
- attributes = List(DiffAttribute, required=True)
122
- relationships = List(DiffRelationship, required=True)
121
+ attributes = List(NonNull(DiffAttribute), required=True)
122
+ relationships = List(NonNull(DiffRelationship), required=True)
123
123
 
124
124
 
125
125
  class DiffTree(DiffSummaryCounts):
@@ -130,7 +130,7 @@ class DiffTree(DiffSummaryCounts):
130
130
  num_untracked_base_changes = Int(required=False)
131
131
  num_untracked_diff_changes = Int(required=False)
132
132
  name = String(required=False)
133
- nodes = List(DiffNode)
133
+ nodes = List(NonNull(DiffNode))
134
134
 
135
135
 
136
136
  class DiffTreeSummary(DiffSummaryCounts):
@@ -145,10 +145,10 @@ class DiffTreeSummary(DiffSummaryCounts):
145
145
 
146
146
  class DiffTreeResolver:
147
147
  async def to_diff_tree(
148
- self, enriched_diff_root: EnrichedDiffRoot, context: GraphqlContext | None = None
148
+ self, enriched_diff_root: EnrichedDiffRoot, graphql_context: GraphqlContext | None = None
149
149
  ) -> DiffTree:
150
150
  all_nodes = list(enriched_diff_root.nodes)
151
- tree_nodes = [self.to_diff_node(enriched_node=e_node, context=context) for e_node in all_nodes]
151
+ tree_nodes = [self.to_diff_node(enriched_node=e_node, graphql_context=graphql_context) for e_node in all_nodes]
152
152
  name = None
153
153
  if enriched_diff_root.tracking_id and isinstance(enriched_diff_root.tracking_id, NameTrackingId):
154
154
  name = enriched_diff_root.tracking_id.name
@@ -165,21 +165,22 @@ class DiffTreeResolver:
165
165
  num_conflicts=enriched_diff_root.num_conflicts,
166
166
  )
167
167
 
168
- def to_diff_node(self, enriched_node: EnrichedDiffNode, context: GraphqlContext | None = None) -> DiffNode:
168
+ def to_diff_node(self, enriched_node: EnrichedDiffNode, graphql_context: GraphqlContext | None = None) -> DiffNode:
169
169
  diff_attributes = [
170
- self.to_diff_attribute(enriched_attribute=e_attr, context=context) for e_attr in enriched_node.attributes
170
+ self.to_diff_attribute(enriched_attribute=e_attr, graphql_context=graphql_context)
171
+ for e_attr in enriched_node.attributes
171
172
  ]
172
173
  diff_relationships = [
173
- self.to_diff_relationship(enriched_relationship=e_rel, context=context)
174
+ self.to_diff_relationship(enriched_relationship=e_rel, graphql_context=graphql_context)
174
175
  for e_rel in enriched_node.relationships
175
176
  if e_rel.include_in_response
176
177
  ]
177
178
  conflict = None
178
179
  if enriched_node.conflict:
179
- conflict = self.to_diff_conflict(enriched_conflict=enriched_node.conflict, context=context)
180
+ conflict = self.to_diff_conflict(enriched_conflict=enriched_node.conflict, graphql_context=graphql_context)
180
181
 
181
182
  parent = None
182
- if parent_info := enriched_node.get_parent_info(context=context):
183
+ if parent_info := enriched_node.get_parent_info(graphql_context=graphql_context):
183
184
  parent = DiffNodeParent(
184
185
  uuid=parent_info.node.uuid,
185
186
  kind=parent_info.node.kind,
@@ -192,7 +193,7 @@ class DiffTreeResolver:
192
193
  label=enriched_node.label,
193
194
  status=enriched_node.action,
194
195
  parent=parent,
195
- last_changed_at=enriched_node.changed_at.obj if enriched_node.changed_at else None,
196
+ last_changed_at=enriched_node.changed_at.to_datetime() if enriched_node.changed_at else None,
196
197
  path_identifier=enriched_node.path_identifier,
197
198
  attributes=diff_attributes,
198
199
  relationships=diff_relationships,
@@ -205,10 +206,11 @@ class DiffTreeResolver:
205
206
  )
206
207
 
207
208
  def to_diff_attribute(
208
- self, enriched_attribute: EnrichedDiffAttribute, context: GraphqlContext | None = None
209
+ self, enriched_attribute: EnrichedDiffAttribute, graphql_context: GraphqlContext | None = None
209
210
  ) -> DiffAttribute:
210
211
  diff_properties = [
211
- self.to_diff_property(enriched_property=e_prop, context=context) for e_prop in enriched_attribute.properties
212
+ self.to_diff_property(enriched_property=e_prop, graphql_context=graphql_context)
213
+ for e_prop in enriched_attribute.properties
212
214
  ]
213
215
  conflict = None
214
216
  for diff_prop in diff_properties:
@@ -217,7 +219,7 @@ class DiffTreeResolver:
217
219
  diff_prop.conflict = None
218
220
  return DiffAttribute(
219
221
  name=enriched_attribute.name,
220
- last_changed_at=enriched_attribute.changed_at.obj,
222
+ last_changed_at=enriched_attribute.changed_at.to_datetime(),
221
223
  status=enriched_attribute.action,
222
224
  path_identifier=enriched_attribute.path_identifier,
223
225
  properties=diff_properties,
@@ -230,16 +232,18 @@ class DiffTreeResolver:
230
232
  )
231
233
 
232
234
  def to_diff_relationship(
233
- self, enriched_relationship: EnrichedDiffRelationship, context: GraphqlContext | None = None
235
+ self, enriched_relationship: EnrichedDiffRelationship, graphql_context: GraphqlContext | None = None
234
236
  ) -> DiffRelationship:
235
237
  diff_elements = [
236
- self.to_diff_relationship_element(enriched_element=element, context=context)
238
+ self.to_diff_relationship_element(enriched_element=element, graphql_context=graphql_context)
237
239
  for element in enriched_relationship.relationships
238
240
  ]
239
241
  return DiffRelationship(
240
242
  name=enriched_relationship.name,
241
243
  label=enriched_relationship.label,
242
- last_changed_at=enriched_relationship.changed_at.obj if enriched_relationship.changed_at else None,
244
+ last_changed_at=enriched_relationship.changed_at.to_datetime()
245
+ if enriched_relationship.changed_at
246
+ else None,
243
247
  status=enriched_relationship.action,
244
248
  cardinality=enriched_relationship.cardinality,
245
249
  path_identifier=enriched_relationship.path_identifier,
@@ -252,14 +256,16 @@ class DiffTreeResolver:
252
256
  )
253
257
 
254
258
  def to_diff_relationship_element(
255
- self, enriched_element: EnrichedDiffSingleRelationship, context: GraphqlContext | None = None
259
+ self, enriched_element: EnrichedDiffSingleRelationship, graphql_context: GraphqlContext | None = None
256
260
  ) -> DiffSingleRelationship:
257
261
  diff_properties = [self.to_diff_property(e_prop) for e_prop in enriched_element.properties]
258
262
  conflict = None
259
263
  if enriched_element.conflict:
260
- conflict = self.to_diff_conflict(enriched_conflict=enriched_element.conflict, context=context)
264
+ conflict = self.to_diff_conflict(
265
+ enriched_conflict=enriched_element.conflict, graphql_context=graphql_context
266
+ )
261
267
  return DiffSingleRelationship(
262
- last_changed_at=enriched_element.changed_at.obj,
268
+ last_changed_at=enriched_element.changed_at.to_datetime(),
263
269
  status=enriched_element.action,
264
270
  peer_id=enriched_element.peer_id,
265
271
  peer_label=enriched_element.peer_label,
@@ -274,14 +280,16 @@ class DiffTreeResolver:
274
280
  )
275
281
 
276
282
  def to_diff_property(
277
- self, enriched_property: EnrichedDiffProperty, context: GraphqlContext | None = None
283
+ self, enriched_property: EnrichedDiffProperty, graphql_context: GraphqlContext | None = None
278
284
  ) -> DiffProperty:
279
285
  conflict = None
280
286
  if enriched_property.conflict:
281
- conflict = self.to_diff_conflict(enriched_conflict=enriched_property.conflict, context=context)
287
+ conflict = self.to_diff_conflict(
288
+ enriched_conflict=enriched_property.conflict, graphql_context=graphql_context
289
+ )
282
290
  return DiffProperty(
283
291
  property_type=enriched_property.property_type.value,
284
- last_changed_at=enriched_property.changed_at.obj,
292
+ last_changed_at=enriched_property.changed_at.to_datetime(),
285
293
  previous_value=enriched_property.previous_value,
286
294
  new_value=enriched_property.new_value,
287
295
  previous_label=enriched_property.previous_label,
@@ -294,19 +302,19 @@ class DiffTreeResolver:
294
302
  def to_diff_conflict(
295
303
  self,
296
304
  enriched_conflict: EnrichedDiffConflict,
297
- context: GraphqlContext | None = None, # pylint: disable=unused-argument
305
+ graphql_context: GraphqlContext | None = None, # noqa: ARG002
298
306
  ) -> ConflictDetails:
299
307
  return ConflictDetails(
300
308
  uuid=enriched_conflict.uuid,
301
309
  base_branch_action=enriched_conflict.base_branch_action,
302
310
  base_branch_value=enriched_conflict.base_branch_value,
303
- base_branch_changed_at=enriched_conflict.base_branch_changed_at.obj
311
+ base_branch_changed_at=enriched_conflict.base_branch_changed_at.to_datetime()
304
312
  if enriched_conflict.base_branch_changed_at
305
313
  else None,
306
314
  base_branch_label=enriched_conflict.base_branch_label,
307
315
  diff_branch_action=enriched_conflict.diff_branch_action,
308
316
  diff_branch_value=enriched_conflict.diff_branch_value,
309
- diff_branch_changed_at=enriched_conflict.diff_branch_changed_at.obj
317
+ diff_branch_changed_at=enriched_conflict.diff_branch_changed_at.to_datetime()
310
318
  if enriched_conflict.diff_branch_changed_at
311
319
  else None,
312
320
  diff_branch_label=enriched_conflict.diff_branch_label,
@@ -366,10 +374,9 @@ class DiffTreeResolver:
366
374
  if diff_branch_name:
367
375
  diff_response.num_untracked_diff_changes = branch_change_map.get(diff_branch_name, 0)
368
376
 
369
- # pylint: disable=unused-argument
370
377
  async def resolve(
371
378
  self,
372
- root: dict,
379
+ root: dict, # noqa: ARG002
373
380
  info: GraphQLResolveInfo,
374
381
  branch: str | None = None,
375
382
  name: str | None = None,
@@ -382,10 +389,10 @@ class DiffTreeResolver:
382
389
  offset: int | None = None,
383
390
  ) -> Optional[Union[list[dict[str, Any]], dict[str, Any]]]:
384
391
  component_registry = get_component_registry()
385
- context: GraphqlContext = info.context
386
- base_branch = await registry.get_branch(db=context.db, branch=registry.default_branch)
387
- diff_branch = await registry.get_branch(db=context.db, branch=branch)
388
- diff_repo = await component_registry.get_component(DiffRepository, db=context.db, branch=diff_branch)
392
+ graphql_context: GraphqlContext = info.context
393
+ base_branch = await registry.get_branch(db=graphql_context.db, branch=registry.default_branch)
394
+ diff_branch = await registry.get_branch(db=graphql_context.db, branch=branch)
395
+ diff_repo = await component_registry.get_component(DiffRepository, db=graphql_context.db, branch=diff_branch)
389
396
  branch_start_timestamp = Timestamp(diff_branch.get_branched_from())
390
397
  if from_time:
391
398
  from_timestamp = Timestamp(from_time.isoformat())
@@ -394,7 +401,7 @@ class DiffTreeResolver:
394
401
  if to_time:
395
402
  to_timestamp = Timestamp(to_time.isoformat())
396
403
  else:
397
- to_timestamp = context.at or Timestamp()
404
+ to_timestamp = graphql_context.at or Timestamp()
398
405
 
399
406
  # Convert filters to dict and merge root_node_uuids for compatibility
400
407
  filters_dict = dict(filters or {})
@@ -421,19 +428,22 @@ class DiffTreeResolver:
421
428
  # take the one with the longest duration that covers multiple branches
422
429
  enriched_diff = sorted(
423
430
  enriched_diffs,
424
- key=lambda d: (d.base_branch_name != d.diff_branch_name, d.to_time.obj - d.from_time.obj),
431
+ key=lambda d: (
432
+ d.base_branch_name != d.diff_branch_name,
433
+ d.to_time.to_datetime() - d.from_time.to_datetime(),
434
+ ),
425
435
  reverse=True,
426
436
  )[0]
427
437
  else:
428
438
  enriched_diff = enriched_diffs[0]
429
439
 
430
440
  full_fields = await extract_fields(info.field_nodes[0].selection_set)
431
- diff_tree = await self.to_diff_tree(enriched_diff_root=enriched_diff, context=context)
441
+ diff_tree = await self.to_diff_tree(enriched_diff_root=enriched_diff, graphql_context=graphql_context)
432
442
  need_base_changes = "num_untracked_base_changes" in full_fields
433
443
  need_branch_changes = "num_untracked_diff_changes" in full_fields
434
444
  if need_base_changes or need_branch_changes:
435
445
  await self._add_untracked_fields(
436
- db=context.db,
446
+ db=graphql_context.db,
437
447
  diff_response=diff_tree,
438
448
  from_time=enriched_diff.to_time,
439
449
  base_branch_name=base_branch.name if need_base_changes else None,
@@ -441,10 +451,9 @@ class DiffTreeResolver:
441
451
  )
442
452
  return await self.to_graphql(fields=full_fields, diff_object=diff_tree)
443
453
 
444
- # pylint: disable=unused-argument
445
454
  async def summary(
446
455
  self,
447
- root: dict,
456
+ root: dict, # noqa: ARG002
448
457
  info: GraphQLResolveInfo,
449
458
  branch: str | None = None,
450
459
  from_time: datetime | None = None,
@@ -452,10 +461,10 @@ class DiffTreeResolver:
452
461
  filters: dict | None = None,
453
462
  ) -> Optional[Union[list[dict[str, Any]], dict[str, Any]]]:
454
463
  component_registry = get_component_registry()
455
- context: GraphqlContext = info.context
456
- base_branch = await registry.get_branch(db=context.db, branch=registry.default_branch)
457
- diff_branch = await registry.get_branch(db=context.db, branch=branch)
458
- diff_repo = await component_registry.get_component(DiffRepository, db=context.db, branch=diff_branch)
464
+ graphql_context: GraphqlContext = info.context
465
+ base_branch = await registry.get_branch(db=graphql_context.db, branch=registry.default_branch)
466
+ diff_branch = await registry.get_branch(db=graphql_context.db, branch=branch)
467
+ diff_repo = await component_registry.get_component(DiffRepository, db=graphql_context.db, branch=diff_branch)
459
468
  branch_start_timestamp = Timestamp(diff_branch.get_branched_from())
460
469
  if from_time:
461
470
  from_timestamp = Timestamp(from_time.isoformat())
@@ -464,7 +473,7 @@ class DiffTreeResolver:
464
473
  if to_time:
465
474
  to_timestamp = Timestamp(to_time.isoformat())
466
475
  else:
467
- to_timestamp = context.at or Timestamp()
476
+ to_timestamp = graphql_context.at or Timestamp()
468
477
 
469
478
  filters_dict = dict(filters or {})
470
479
 
@@ -481,8 +490,8 @@ class DiffTreeResolver:
481
490
  diff_tree_summary = DiffTreeSummary(
482
491
  base_branch=base_branch.name,
483
492
  diff_branch=diff_branch.name,
484
- from_time=summary.from_time.obj,
485
- to_time=summary.to_time.obj,
493
+ from_time=summary.from_time.to_datetime(),
494
+ to_time=summary.to_time.to_datetime(),
486
495
  **summary.model_dump(exclude={"from_time", "to_time"}),
487
496
  )
488
497
  full_fields = await extract_fields(info.field_nodes[0].selection_set)
@@ -490,7 +499,7 @@ class DiffTreeResolver:
490
499
  need_branch_changes = "num_untracked_diff_changes" in full_fields
491
500
  if need_base_changes or need_branch_changes:
492
501
  await self._add_untracked_fields(
493
- db=context.db,
502
+ db=graphql_context.db,
494
503
  diff_response=diff_tree_summary,
495
504
  from_time=summary.to_time,
496
505
  base_branch_name=base_branch.name if need_base_changes else None,
@@ -519,7 +528,6 @@ class DiffTreeQueryFilters(InputObjectType):
519
528
  DiffTreeQuery = Field(
520
529
  DiffTree,
521
530
  name=String(),
522
- resolver=DiffTreeResolver().resolve,
523
531
  branch=String(),
524
532
  from_time=DateTime(),
525
533
  to_time=DateTime(),
@@ -528,14 +536,17 @@ DiffTreeQuery = Field(
528
536
  filters=DiffTreeQueryFilters(),
529
537
  limit=Int(),
530
538
  offset=Int(),
539
+ resolver=DiffTreeResolver().resolve,
540
+ required=False,
531
541
  )
532
542
 
533
543
  DiffTreeSummaryQuery = Field(
534
544
  DiffTreeSummary,
535
545
  name=String(),
536
- resolver=DiffTreeResolver().summary,
537
546
  branch=String(),
538
547
  from_time=DateTime(),
539
548
  to_time=DateTime(),
540
549
  filters=DiffTreeQueryFilters(),
550
+ resolver=DiffTreeResolver().summary,
551
+ required=False,
541
552
  )
@@ -0,0 +1,115 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any
4
+
5
+ from graphene import Argument, Boolean, DateTime, Field, Int, List, NonNull, ObjectType, String
6
+ from infrahub_sdk.utils import extract_fields_first_node
7
+
8
+ from infrahub.exceptions import ValidationError
9
+ from infrahub.graphql.types.event import EventNodes, EventTypeFilter
10
+ from infrahub.task_manager.event import PrefectEvent
11
+ from infrahub.task_manager.models import InfrahubEventFilter
12
+
13
+ if TYPE_CHECKING:
14
+ from datetime import datetime
15
+
16
+ from graphql import GraphQLResolveInfo
17
+
18
+
19
+ class Events(ObjectType):
20
+ edges = List(NonNull(EventNodes), required=True)
21
+ count = Int(required=True)
22
+
23
+ @staticmethod
24
+ async def resolve(
25
+ root: dict, # noqa: ARG004
26
+ info: GraphQLResolveInfo,
27
+ limit: int = 10,
28
+ has_children: bool | None = None,
29
+ level: int | None = None,
30
+ offset: int | None = None,
31
+ account__ids: list[str] | None = None,
32
+ ids: list[str] | None = None,
33
+ branches: list[str] | None = None,
34
+ event_type: list[str] | None = None,
35
+ event_type_filter: dict[str, Any] | None = None,
36
+ related_node__ids: list[str] | None = None,
37
+ primary_node__ids: list[str] | None = None,
38
+ parent__ids: list[str] | None = None,
39
+ since: datetime | None = None,
40
+ until: datetime | None = None,
41
+ ) -> dict[str, Any]:
42
+ ids = ids or []
43
+ if limit > 50:
44
+ # Prefect restricts this to 50
45
+ raise ValidationError(input_value="The parameter 'limit' can't be above 50")
46
+
47
+ event_filter = InfrahubEventFilter.from_filters(
48
+ ids=ids,
49
+ branches=branches,
50
+ account__ids=account__ids,
51
+ has_children=has_children,
52
+ event_type=event_type,
53
+ event_type_filter=event_type_filter,
54
+ related_node__ids=related_node__ids,
55
+ primary_node__ids=primary_node__ids,
56
+ parent__ids=parent__ids,
57
+ since=since,
58
+ until=until,
59
+ level=level,
60
+ )
61
+
62
+ return await Events.query(
63
+ info=info,
64
+ event_filter=event_filter,
65
+ limit=limit,
66
+ offset=offset,
67
+ )
68
+
69
+ @classmethod
70
+ async def query(
71
+ cls,
72
+ info: GraphQLResolveInfo,
73
+ event_filter: InfrahubEventFilter,
74
+ limit: int,
75
+ offset: int | None = None,
76
+ ) -> dict[str, Any]:
77
+ fields = await extract_fields_first_node(info)
78
+
79
+ prefect_tasks = await PrefectEvent.query(
80
+ fields=fields,
81
+ event_filter=event_filter,
82
+ limit=limit,
83
+ offset=offset,
84
+ )
85
+ return {
86
+ "count": prefect_tasks.get("count", 0),
87
+ "edges": prefect_tasks.get("edges", []),
88
+ }
89
+
90
+
91
+ Event = Field(
92
+ Events,
93
+ limit=Int(required=False),
94
+ offset=Int(required=False),
95
+ level=Int(required=False),
96
+ has_children=Boolean(required=False, description="Filter events based on if they can have children or not"),
97
+ event_type=List(NonNull(String), description="Filter events that match a specific type"),
98
+ event_type_filter=Argument(EventTypeFilter, required=False, description="Filters specific to a given event_type"),
99
+ primary_node__ids=List(
100
+ NonNull(String), description="Filter events where the primary node id is within indicated node ids"
101
+ ),
102
+ related_node__ids=List(
103
+ NonNull(String), description="Filter events where the related node ids are within indicated node ids"
104
+ ),
105
+ parent__ids=List(
106
+ NonNull(String), description="Search events that has any of the indicated event ids listed as parents"
107
+ ),
108
+ since=DateTime(required=False, description="Search events since this timestamp, defaults to 180 days back"),
109
+ until=DateTime(required=False, description="Search events until this timestamp, defaults the current time"),
110
+ branches=List(NonNull(String), required=False, description="Filter the query to specific branches"),
111
+ account__ids=List(NonNull(String), required=False, description="Filter the query to specific accounts"),
112
+ ids=List(NonNull(String)),
113
+ resolver=Events.resolve,
114
+ required=True,
115
+ )
@@ -17,10 +17,10 @@ class Info(ObjectType):
17
17
 
18
18
  @staticmethod
19
19
  async def resolve(
20
- root: dict, # pylint: disable=unused-argument
21
- info: GraphQLResolveInfo, # pylint: disable=unused-argument
20
+ root: dict, # noqa: ARG004
21
+ info: GraphQLResolveInfo, # noqa: ARG004
22
22
  ) -> dict[str, str]:
23
23
  return {"deployment_id": str(registry.id), "version": __version__}
24
24
 
25
25
 
26
- InfrahubInfo = Field(Info, resolver=Info.resolve)
26
+ InfrahubInfo = Field(Info, resolver=Info.resolve, required=True)