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
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from prefect import flow
2
4
 
3
5
  from infrahub.core import registry
@@ -7,7 +9,7 @@ from infrahub.core.diff.repository.repository import DiffRepository
7
9
  from infrahub.dependencies.registry import get_component_registry
8
10
  from infrahub.log import get_logger
9
11
  from infrahub.message_bus import InfrahubMessage, messages
10
- from infrahub.services import InfrahubServices
12
+ from infrahub.services import InfrahubServices # noqa: TC001 needed for prefect flow
11
13
  from infrahub.workflows.catalogue import (
12
14
  DIFF_UPDATE,
13
15
  TRIGGER_ARTIFACT_DEFINITION_GENERATE,
@@ -33,11 +35,13 @@ async def merge(message: messages.EventBranchMerge, service: InfrahubServices) -
33
35
 
34
36
  await service.workflow.submit_workflow(
35
37
  workflow=TRIGGER_ARTIFACT_DEFINITION_GENERATE,
38
+ context=message.context,
36
39
  parameters={"branch": message.target_branch},
37
40
  )
38
41
 
39
42
  await service.workflow.submit_workflow(
40
43
  workflow=TRIGGER_GENERATOR_DEFINITION_RUN,
44
+ context=message.context,
41
45
  parameters={"branch": message.target_branch},
42
46
  )
43
47
 
@@ -49,9 +53,9 @@ async def merge(message: messages.EventBranchMerge, service: InfrahubServices) -
49
53
  ):
50
54
  request_diff_update_model = RequestDiffUpdate(branch_name=diff_root.diff_branch_name)
51
55
  await service.workflow.submit_workflow(
52
- workflow=DIFF_UPDATE, parameters={"model": request_diff_update_model}
56
+ workflow=DIFF_UPDATE, context=message.context, parameters={"model": request_diff_update_model}
53
57
  )
54
58
 
55
59
  for event in events:
56
60
  event.assign_meta(parent=message)
57
- await service.send(message=event)
61
+ await service.message_bus.send(message=event)
@@ -14,4 +14,4 @@ async def update(message: messages.EventSchemaUpdate, service: InfrahubServices)
14
14
  msg = messages.RefreshRegistryBranches()
15
15
 
16
16
  msg.assign_meta(parent=message)
17
- await service.send(message=msg)
17
+ await service.message_bus.send(message=msg)
@@ -2,11 +2,8 @@ from prefect import flow
2
2
 
3
3
  from infrahub.message_bus import messages
4
4
  from infrahub.services import InfrahubServices
5
- from infrahub.workflows.catalogue import WEBHOOK_CONFIGURE
6
5
 
7
6
 
8
7
  @flow(name="event-worker-newprimary-api")
9
8
  async def new_primary_api(message: messages.EventWorkerNewPrimaryAPI, service: InfrahubServices) -> None:
10
9
  service.log.info("api_worker promoted to primary", worker_id=message.worker_id)
11
-
12
- await service.workflow.submit_workflow(workflow=WEBHOOK_CONFIGURE)
@@ -67,7 +67,7 @@ async def execution(message: messages.FinalizeValidatorExecution, service: Infra
67
67
  validator_id=message.validator_id,
68
68
  validator_execution_id=message.validator_execution_id,
69
69
  )
70
- await service.send(message=message, delay=MessageTTL.FIVE)
70
+ await service.message_bus.send(message=message, delay=MessageTTL.FIVE)
71
71
  return
72
72
 
73
73
  log.info(
@@ -27,8 +27,8 @@ async def get(message: messages.GitFileGet, service: InfrahubServices) -> None:
27
27
  except (FileOutOfRepositoryError, RepositoryFileNotFoundError) as e:
28
28
  if message.reply_requested:
29
29
  response = GitFileGetResponse(data=GitFileGetResponseData(error_message=e.message, http_code=e.HTTP_CODE))
30
- await service.reply(message=response, initiator=message)
30
+ await service.message_bus.reply_if_initiator_meta(message=response, initiator=message)
31
31
  else:
32
32
  if message.reply_requested:
33
33
  response = GitFileGetResponse(data=GitFileGetResponseData(content=content))
34
- await service.reply(message=response, initiator=message)
34
+ await service.message_bus.reply_if_initiator_meta(message=response, initiator=message)
@@ -28,7 +28,7 @@ async def connectivity(message: messages.GitRepositoryConnectivity, service: Inf
28
28
  response = GitRepositoryConnectivityResponse(
29
29
  data=response_data,
30
30
  )
31
- await service.reply(message=response, initiator=message)
31
+ await service.message_bus.reply_if_initiator_meta(message=response, initiator=message)
32
32
 
33
33
 
34
34
  @flow(name="refresh-git-fetch", flow_run_name="Fetch git repository {message.repository_name} on " + WORKER_IDENTITY)
@@ -1,13 +1,9 @@
1
1
  from . import (
2
- artifact_definition,
3
2
  generator_definition,
4
3
  proposed_change,
5
- repository,
6
4
  )
7
5
 
8
6
  __all__ = [
9
- "artifact_definition",
10
7
  "generator_definition",
11
8
  "proposed_change",
12
- "repository",
13
9
  ]
@@ -1,5 +1,3 @@
1
- from typing import Optional
2
-
3
1
  from infrahub_sdk.uuidt import UUIDT
4
2
  from prefect import flow
5
3
  from prefect.logging import get_run_logger
@@ -125,10 +123,10 @@ async def check(message: messages.RequestGeneratorDefinitionCheck, service: Infr
125
123
  )
126
124
  for event in events:
127
125
  event.assign_meta(parent=message)
128
- await service.send(message=event)
126
+ await service.message_bus.send(message=event)
129
127
 
130
128
 
131
- def _run_generator(instance_id: Optional[str], managed_branch: bool, impacted_instances: list[str]) -> bool:
129
+ def _run_generator(instance_id: str | None, managed_branch: bool, impacted_instances: list[str]) -> bool:
132
130
  """Returns a boolean to indicate if a generator instance needs to be executed
133
131
  Will return true if:
134
132
  * The instance_id wasn't set which could be that it's a new object that doesn't have a previous generator instance
@@ -11,6 +11,7 @@ from infrahub.core.constants import CheckType, InfrahubKind, RepositoryInternalS
11
11
  from infrahub.core.diff.coordinator import DiffCoordinator
12
12
  from infrahub.core.registry import registry
13
13
  from infrahub.dependencies.registry import get_component_registry
14
+ from infrahub.git.models import TriggerRepositoryInternalChecks
14
15
  from infrahub.git.repository import InfrahubRepository
15
16
  from infrahub.message_bus import InfrahubMessage, messages
16
17
  from infrahub.message_bus.types import (
@@ -20,6 +21,7 @@ from infrahub.message_bus.types import (
20
21
  ProposedChangeSubscriber,
21
22
  )
22
23
  from infrahub.proposed_change.models import (
24
+ RequestArtifactDefinitionCheck,
23
25
  RequestProposedChangeDataIntegrity,
24
26
  RequestProposedChangeRepositoryChecks,
25
27
  RequestProposedChangeRunGenerators,
@@ -28,6 +30,8 @@ from infrahub.proposed_change.models import (
28
30
  )
29
31
  from infrahub.services import InfrahubServices # noqa: TC001
30
32
  from infrahub.workflows.catalogue import (
33
+ GIT_REPOSITORY_INTERNAL_CHECKS_TRIGGER,
34
+ REQUEST_ARTIFACT_DEFINITION_CHECK,
31
35
  REQUEST_PROPOSED_CHANGE_DATA_INTEGRITY,
32
36
  REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
33
37
  REQUEST_PROPOSED_CHANGE_RUN_GENERATORS,
@@ -74,17 +78,15 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
74
78
  ):
75
79
  for repo in repositories:
76
80
  if not repo.read_only and repo.internal_status == RepositoryInternalStatus.ACTIVE.value:
77
- events.append(
78
- messages.RequestRepositoryChecks(
79
- proposed_change=message.proposed_change,
80
- repository=repo.repository_id,
81
- source_branch=repo.source_branch,
82
- target_branch=repo.destination_branch,
83
- )
81
+ model = TriggerRepositoryInternalChecks(
82
+ proposed_change=message.proposed_change,
83
+ repository=repo.repository_id,
84
+ source_branch=repo.source_branch,
85
+ target_branch=repo.destination_branch,
86
+ )
87
+ await service.workflow.submit_workflow(
88
+ workflow=GIT_REPOSITORY_INTERNAL_CHECKS_TRIGGER, parameters={"model": model}
84
89
  )
85
- for event in events:
86
- event.assign_meta(parent=message)
87
- await service.send(message=event)
88
90
  return
89
91
 
90
92
  await _gather_repository_repository_diffs(repositories=repositories, service=service)
@@ -103,6 +105,7 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
103
105
  if message.check_type is CheckType.ARTIFACT:
104
106
  events.append(
105
107
  messages.RequestProposedChangeRefreshArtifacts(
108
+ context=message.context,
106
109
  proposed_change=message.proposed_change,
107
110
  source_branch=message.source_branch,
108
111
  source_branch_sync_with_git=message.source_branch_sync_with_git,
@@ -122,7 +125,9 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
122
125
  do_repository_checks=message.check_type is CheckType.ALL,
123
126
  )
124
127
  await service.workflow.submit_workflow(
125
- workflow=REQUEST_PROPOSED_CHANGE_RUN_GENERATORS, parameters={"model": model_proposed_change_run_generator}
128
+ workflow=REQUEST_PROPOSED_CHANGE_RUN_GENERATORS,
129
+ context=message.context,
130
+ parameters={"model": model_proposed_change_run_generator},
126
131
  )
127
132
 
128
133
  if message.check_type in [CheckType.ALL, CheckType.DATA] and branch_diff.has_node_changes(
@@ -136,7 +141,9 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
136
141
  branch_diff=branch_diff,
137
142
  )
138
143
  await service.workflow.submit_workflow(
139
- workflow=REQUEST_PROPOSED_CHANGE_DATA_INTEGRITY, parameters={"model": model_proposed_change_data_integrity}
144
+ workflow=REQUEST_PROPOSED_CHANGE_DATA_INTEGRITY,
145
+ context=message.context,
146
+ parameters={"model": model_proposed_change_data_integrity},
140
147
  )
141
148
 
142
149
  if message.check_type in [CheckType.REPOSITORY, CheckType.USER]:
@@ -148,7 +155,9 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
148
155
  branch_diff=branch_diff,
149
156
  )
150
157
  await service.workflow.submit_workflow(
151
- workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS, parameters={"model": model_proposed_change_repo_checks}
158
+ workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
159
+ context=message.context,
160
+ parameters={"model": model_proposed_change_repo_checks},
152
161
  )
153
162
 
154
163
  if message.check_type in [CheckType.ALL, CheckType.SCHEMA] and branch_diff.has_data_changes(
@@ -156,6 +165,7 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
156
165
  ):
157
166
  await service.workflow.submit_workflow(
158
167
  workflow=REQUEST_PROPOSED_CHANGE_SCHEMA_INTEGRITY,
168
+ context=message.context,
159
169
  parameters={
160
170
  "model": RequestProposedChangeSchemaIntegrity(
161
171
  proposed_change=message.proposed_change,
@@ -170,6 +180,7 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
170
180
  if message.check_type in [CheckType.ALL, CheckType.TEST]:
171
181
  await service.workflow.submit_workflow(
172
182
  workflow=REQUEST_PROPOSED_CHANGE_USER_TESTS,
183
+ context=message.context,
173
184
  parameters={
174
185
  "model": RequestProposedChangeUserTests(
175
186
  proposed_change=message.proposed_change,
@@ -183,7 +194,7 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
183
194
 
184
195
  for event in events:
185
196
  event.assign_meta(parent=message)
186
- await service.send(message=event)
197
+ await service.message_bus.send(message=event)
187
198
 
188
199
 
189
200
  @flow(
@@ -232,7 +243,8 @@ async def refresh_artifacts(message: messages.RequestProposedChangeRefreshArtifa
232
243
 
233
244
  if select:
234
245
  log.info(f"Trigger processing of {artifact_definition.definition_name}")
235
- msg = messages.RequestArtifactDefinitionCheck(
246
+ model = RequestArtifactDefinitionCheck(
247
+ context=message.context,
236
248
  artifact_definition=artifact_definition,
237
249
  branch_diff=message.branch_diff,
238
250
  proposed_change=message.proposed_change,
@@ -241,8 +253,7 @@ async def refresh_artifacts(message: messages.RequestProposedChangeRefreshArtifa
241
253
  destination_branch=message.destination_branch,
242
254
  )
243
255
 
244
- msg.assign_meta(parent=message)
245
- await service.send(message=msg)
256
+ await service.workflow.submit_workflow(REQUEST_ARTIFACT_DEFINITION_CHECK, parameters={"model": model})
246
257
 
247
258
 
248
259
  GATHER_ARTIFACT_DEFINITIONS = """
@@ -520,7 +531,7 @@ async def _get_proposed_change_repositories(
520
531
  return _parse_proposed_change_repositories(message=message, source=source_all, destination=destination_all)
521
532
 
522
533
 
523
- @task(name="proposed-change-validate-repository-conflicts", task_run_name="Validate conflicts on repository")
534
+ @task(name="proposed-change-validate-repository-conflicts", task_run_name="Validate conflicts on repository") # type: ignore[arg-type]
524
535
  async def _validate_repository_merge_conflicts(
525
536
  repositories: list[ProposedChangeRepository], service: InfrahubServices
526
537
  ) -> bool:
@@ -529,7 +540,10 @@ async def _validate_repository_merge_conflicts(
529
540
  for repo in repositories:
530
541
  if repo.has_diff and not repo.is_staging:
531
542
  git_repo = await InfrahubRepository.init(
532
- id=repo.repository_id, name=repo.repository_name, client=service.client
543
+ id=repo.repository_id,
544
+ name=repo.repository_name,
545
+ client=service.client,
546
+ service=service,
533
547
  )
534
548
  async with lock.registry.get(name=repo.repository_name, namespace="repository"):
535
549
  repo.conflicts = await git_repo.get_conflicts(
@@ -551,7 +565,10 @@ async def _gather_repository_repository_diffs(
551
565
  if repo.has_diff and repo.source_commit and repo.destination_commit:
552
566
  # TODO we need to find a way to return all files in the repo if the repo is new
553
567
  git_repo = await InfrahubRepository.init(
554
- id=repo.repository_id, name=repo.repository_name, client=service.client
568
+ id=repo.repository_id,
569
+ name=repo.repository_name,
570
+ client=service.client,
571
+ service=service,
555
572
  )
556
573
 
557
574
  files_changed: list[str] = []
@@ -10,4 +10,4 @@ async def request(message: messages.SendEchoRequest, service: InfrahubServices)
10
10
  service.log.info(f"Received message: {message.message}")
11
11
  if message.reply_requested:
12
12
  response = SendEchoRequestResponse(data=SendEchoRequestResponseData(response=f"Reply to: {message.message}"))
13
- await service.reply(message=response, initiator=message)
13
+ await service.message_bus.reply_if_initiator_meta(message=response, initiator=message)
@@ -9,7 +9,7 @@ from pydantic import BaseModel, Field
9
9
  from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus
10
10
  from infrahub.exceptions import NodeNotFoundError
11
11
 
12
- SCHEMA_CHANGE = re.compile("^Schema[A-Z]")
12
+ SCHEMA_CHANGE = re.compile(r"^Schema[A-Z]")
13
13
 
14
14
 
15
15
  class MessageTTL(int, Enum):
@@ -2,12 +2,13 @@ from infrahub.permissions.backend import PermissionBackend
2
2
  from infrahub.permissions.local_backend import LocalPermissionBackend
3
3
  from infrahub.permissions.manager import PermissionManager
4
4
  from infrahub.permissions.report import report_schema_permissions
5
- from infrahub.permissions.types import AssignedPermissions
5
+ from infrahub.permissions.types import AssignedPermissions, get_global_permission_for_kind
6
6
 
7
7
  __all__ = [
8
8
  "AssignedPermissions",
9
9
  "LocalPermissionBackend",
10
10
  "PermissionBackend",
11
11
  "PermissionManager",
12
+ "get_global_permission_for_kind",
12
13
  "report_schema_permissions",
13
14
  ]
@@ -0,0 +1,15 @@
1
+ from infrahub.core.account import GlobalPermission
2
+ from infrahub.core.constants import GLOBAL_BRANCH_NAME, GlobalPermissions, PermissionDecision
3
+ from infrahub.core.registry import registry
4
+
5
+
6
+ def define_global_permission_from_branch(permission: GlobalPermissions, branch_name: str) -> GlobalPermission:
7
+ if branch_name in (GLOBAL_BRANCH_NAME, registry.default_branch):
8
+ decision = PermissionDecision.ALLOW_DEFAULT
9
+ else:
10
+ decision = PermissionDecision.ALLOW_OTHER
11
+
12
+ return GlobalPermission(
13
+ action=permission.value,
14
+ decision=decision.value,
15
+ )
@@ -2,8 +2,12 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING, TypedDict
4
4
 
5
+ from infrahub.core.constants import GlobalPermissions, InfrahubKind
6
+ from infrahub.core.schema import NodeSchema
7
+
5
8
  if TYPE_CHECKING:
6
9
  from infrahub.core.account import GlobalPermission, ObjectPermission
10
+ from infrahub.core.schema import MainSchemaTypes
7
11
  from infrahub.permissions.constants import BranchRelativePermissionDecision
8
12
 
9
13
 
@@ -18,3 +22,25 @@ class KindPermissions(TypedDict):
18
22
  delete: BranchRelativePermissionDecision
19
23
  update: BranchRelativePermissionDecision
20
24
  view: BranchRelativePermissionDecision
25
+
26
+
27
+ def get_global_permission_for_kind(schema: MainSchemaTypes) -> GlobalPermissions | None:
28
+ kind_permission_map = {
29
+ InfrahubKind.GENERICACCOUNT: GlobalPermissions.MANAGE_ACCOUNTS,
30
+ InfrahubKind.ACCOUNTGROUP: GlobalPermissions.MANAGE_ACCOUNTS,
31
+ InfrahubKind.ACCOUNTROLE: GlobalPermissions.MANAGE_ACCOUNTS,
32
+ InfrahubKind.BASEPERMISSION: GlobalPermissions.MANAGE_PERMISSIONS,
33
+ InfrahubKind.GENERICREPOSITORY: GlobalPermissions.MANAGE_REPOSITORIES,
34
+ }
35
+
36
+ if schema.kind in kind_permission_map:
37
+ return kind_permission_map[schema.kind]
38
+
39
+ if isinstance(schema, NodeSchema):
40
+ for base in schema.inherit_from:
41
+ try:
42
+ return kind_permission_map[base]
43
+ except KeyError:
44
+ continue
45
+
46
+ return None
infrahub/pools/prefix.py CHANGED
@@ -1,174 +1,38 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import ipaddress
4
- from collections import OrderedDict, defaultdict
5
- from ipaddress import IPv4Network, IPv6Network
6
- from typing import Optional, Union
4
+ from typing import TYPE_CHECKING, Literal
7
5
 
6
+ from netaddr import IPSet
8
7
 
9
- class PrefixPool:
10
- """
11
- Class to automatically manage Prefixes and help to carve out sub-prefixes
12
- """
13
-
14
- def __init__(self, network: str) -> None:
15
- self.network = ipaddress.ip_network(network)
16
-
17
- # Define biggest and smallest possible masks
18
- self.mask_biggest = self.network.prefixlen + 1
19
- if self.network.version == 4:
20
- self.mask_smallest = 32
21
- else:
22
- self.mask_smallest = 128
23
-
24
- self.available_subnets = defaultdict(list)
25
- self.sub_by_key: dict[str, Optional[str]] = OrderedDict()
26
- self.sub_by_id: dict[str, str] = OrderedDict()
27
-
28
- # Save the top level available subnet
29
- for subnet in list(self.network.subnets(new_prefix=self.mask_biggest)):
30
- self.available_subnets[self.mask_biggest].append(str(subnet))
31
-
32
- def reserve(self, subnet: str, identifier: Optional[str] = None) -> bool:
33
- """
34
- Indicate that a specific subnet is already reserved/used
35
- """
36
-
37
- # TODO Add check to make sure the subnet provided has the right size
38
- sub = ipaddress.ip_network(subnet)
39
-
40
- if int(sub.prefixlen) <= int(self.network.prefixlen):
41
- raise ValueError(f"{subnet} do not have the right size ({sub.prefixlen},{self.network.prefixlen})")
42
-
43
- if sub.supernet(new_prefix=self.network.prefixlen) != self.network:
44
- raise ValueError(f"{subnet} is not part of this network")
45
-
46
- # Check first if this ID as already done a reservation
47
- if identifier and identifier in self.sub_by_id.keys():
48
- if self.sub_by_id[identifier] == str(sub):
49
- return True
50
- raise ValueError(
51
- f"this identifier ({identifier}) is already used but for a different resource ({self.sub_by_id[identifier]})"
52
- )
53
-
54
- if identifier and str(sub) in self.sub_by_key.keys():
55
- raise ValueError(f"this subnet is already reserved but not with this identifier ({identifier})")
56
-
57
- if str(sub) in self.sub_by_key.keys():
58
- self.remove_subnet_from_available_list(sub)
59
- return True
60
-
61
- # Check if the subnet itself is available
62
- # if available reserve and return
63
- if subnet in self.available_subnets[sub.prefixlen]:
64
- if identifier:
65
- self.sub_by_id[identifier] = subnet
66
- self.sub_by_key[subnet] = identifier
67
- else:
68
- self.sub_by_key[subnet] = None
69
-
70
- self.remove_subnet_from_available_list(sub)
71
- return True
72
-
73
- # If not reserved already, check if the subnet is available
74
- # start at sublen and check all available subnet
75
- # increase 1 by 1 until we find the closer supernet available
76
- # break it down and keep track of the other available subnets
8
+ if TYPE_CHECKING:
9
+ from infrahub.core.ipam.constants import IPNetworkType
77
10
 
78
- for sublen in range(sub.prefixlen - 1, self.network.prefixlen, -1):
79
- supernet = sub.supernet(new_prefix=sublen)
80
- if str(supernet) in self.available_subnets[sublen]:
81
- self.split_supernet(supernet=supernet, subnet=sub)
82
- return self.reserve(subnet=subnet, identifier=identifier)
83
11
 
84
- return False
12
+ def get_next_available_prefix(pool: IPSet, prefix_length: int, prefix_ver: Literal[4, 6] = 4) -> IPNetworkType:
13
+ """Get the next available prefix of a given prefix length from an IPSet.
85
14
 
86
- def get(self, prefixlen: int, identifier: Optional[str] = None) -> Union[IPv4Network, IPv6Network]:
87
- """Return the next available Subnet."""
15
+ Args:
16
+ pool: netaddr IPSet object with available subnets
17
+ prefix_length: length of the desired prefix
18
+ prefix_ver: IPSet can contain a mix of IPv4 and IPv6 subnets. This parameter specifies the IP version of prefix to acquire.
88
19
 
89
- clean_prefixlen = int(prefixlen)
90
-
91
- if identifier and identifier in self.sub_by_id.keys():
92
- net = ipaddress.ip_network(self.sub_by_id[identifier])
93
- if net.prefixlen == clean_prefixlen:
94
- return net
95
- raise ValueError()
96
-
97
- if len(self.available_subnets[clean_prefixlen]) != 0:
98
- sub = self.available_subnets[clean_prefixlen][0]
99
- self.reserve(subnet=sub, identifier=identifier)
100
- return ipaddress.ip_network(sub)
101
-
102
- # if a subnet of this size is not available
103
- # we need to find the closest subnet available and split it
104
- for i in range(clean_prefixlen - 1, self.mask_biggest - 1, -1):
105
- if len(self.available_subnets[i]) != 0:
106
- supernet = ipaddress.ip_network(self.available_subnets[i][0])
107
- # supernet available, will split it
108
- subs = supernet.subnets(new_prefix=clean_prefixlen)
109
- next_sub: Union[IPv4Network, IPv6Network] = next(subs) # type: ignore[assignment]
110
- self.split_supernet(supernet=supernet, subnet=next_sub)
111
- self.reserve(subnet=str(next_sub), identifier=identifier)
112
- return next_sub
113
-
114
- raise IndexError("No More subnet available")
115
-
116
- def get_nbr_available_subnets(self) -> dict[int, int]:
117
- tmp = {}
118
- for i in range(self.mask_biggest, self.mask_smallest + 1):
119
- tmp[i] = len(self.available_subnets[i])
120
-
121
- return tmp
122
-
123
- def check_if_already_allocated(self, identifier: str) -> bool:
124
- """
125
- Check if a subnet has already been allocated based on an identifier
126
-
127
- Need to add the same capability based on Network address
128
- If both identifier and subnet are provided, identifier take precedence
129
- """
130
- if identifier in self.sub_by_id.keys():
131
- return True
132
- return False
133
-
134
- def split_supernet(
135
- self, supernet: Union[IPv4Network, IPv6Network], subnet: Union[IPv4Network, IPv6Network]
136
- ) -> None:
137
- """Split a supernet into smaller networks"""
138
-
139
- # TODO ensure subnet is small than supernet
140
- # TODO ensure that subnet is part of supernet
141
- parent_net = supernet
142
- for i in range(supernet.prefixlen + 1, subnet.prefixlen + 1):
143
- tmp_net: list[Union[IPv4Network, IPv6Network]] = list(parent_net.subnets(new_prefix=i))
144
-
145
- if i == subnet.prefixlen:
146
- for net in tmp_net:
147
- self.available_subnets[i].append(str(net))
148
- else:
149
- if subnet.subnet_of(other=tmp_net[0]): # type: ignore[arg-type]
150
- parent = 0
151
- other = 1
152
- else:
153
- parent = 1
154
- other = 0
155
-
156
- parent_net = tmp_net[parent]
157
- self.available_subnets[i].append(str(tmp_net[other]))
158
-
159
- self.remove_subnet_from_available_list(supernet)
160
-
161
- def remove_subnet_from_available_list(self, subnet: Union[IPv4Network, IPv6Network]) -> None:
162
- """Remove a subnet from the list of available Subnet."""
163
- try:
164
- idx = self.available_subnets[subnet.prefixlen].index(str(subnet))
165
- del self.available_subnets[subnet.prefixlen][idx]
166
- except ValueError:
167
- # Already removed
168
- pass
169
-
170
- # if idx:
171
- # return True
172
- # except:
173
- # log.warn("Unable to remove %s from list of available subnets" % str(subnet))
174
- # return False
20
+ Raises:
21
+ ValueError: If there are no available subnets in the pool
22
+ """
23
+ prefix_ver_map = {
24
+ 4: ipaddress.IPv4Network,
25
+ 6: ipaddress.IPv6Network,
26
+ }
27
+
28
+ filtered_pool = IPSet([])
29
+ for subnet in pool.iter_cidrs():
30
+ if isinstance(ipaddress.ip_network(str(subnet)), prefix_ver_map[prefix_ver]):
31
+ filtered_pool.add(subnet)
32
+
33
+ for cidr in filtered_pool.iter_cidrs():
34
+ if cidr.prefixlen <= prefix_length:
35
+ next_available = ipaddress.ip_network(f"{cidr.network}/{prefix_length}")
36
+ return next_available
37
+
38
+ raise ValueError("No available subnets in pool")
File without changes
@@ -0,0 +1,18 @@
1
+ from __future__ import annotations
2
+
3
+ from fastapi import APIRouter, FastAPI
4
+ from prefect.server.api.server import create_app
5
+
6
+ from . import events
7
+
8
+ router = APIRouter(prefix="/infrahub")
9
+
10
+ router.include_router(events.router)
11
+
12
+
13
+ def create_infrahub_prefect() -> FastAPI:
14
+ app = create_app()
15
+ api_app: FastAPI = app.__dict__["api_app"]
16
+ api_app.include_router(router=router)
17
+
18
+ return app
@@ -0,0 +1,20 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from prefect.server.events.schemas.events import ReceivedEvent
6
+ from prefect.server.events.storage import INTERACTIVE_PAGE_SIZE
7
+ from prefect.server.events.storage.database import raw_count_events, read_events
8
+
9
+ if TYPE_CHECKING:
10
+ from prefect.server.events.filters import EventFilter
11
+ from sqlalchemy.ext.asyncio import AsyncSession
12
+
13
+
14
+ async def query_events(
15
+ session: AsyncSession, filter: EventFilter, page_size: int = INTERACTIVE_PAGE_SIZE, offset: int | None = None
16
+ ) -> tuple[list[ReceivedEvent], int]:
17
+ count = await raw_count_events(session, filter) # type: ignore[attr-defined]
18
+ page = await read_events(session, filter, limit=page_size, offset=offset) # type: ignore[attr-defined]
19
+ events = [ReceivedEvent.model_validate(e, from_attributes=True) for e in page]
20
+ return events, count
@@ -0,0 +1,28 @@
1
+ from fastapi import APIRouter
2
+ from fastapi.param_functions import Depends
3
+ from prefect.server.database import PrefectDBInterface, provide_database_interface
4
+
5
+ from .database import query_events
6
+ from .models import InfrahubEventfilterInput, InfrahubEventPage
7
+
8
+ router = APIRouter(prefix="/events", tags=["Infrahub"])
9
+
10
+
11
+ @router.post(
12
+ "/filter",
13
+ )
14
+ async def read_events(
15
+ event_filter: InfrahubEventfilterInput,
16
+ db: PrefectDBInterface = Depends(provide_database_interface), # noqa: B008
17
+ ) -> InfrahubEventPage:
18
+ event_filter.filter.set_prefix()
19
+
20
+ async with db.session_context() as session:
21
+ events, total = await query_events(
22
+ session=session, filter=event_filter.filter, page_size=event_filter.limit, offset=event_filter.offset
23
+ )
24
+
25
+ return InfrahubEventPage(
26
+ events=events,
27
+ total=total,
28
+ )