infrahub-server 1.2.0rc0__py3-none-any.whl → 1.2.1__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 (365) hide show
  1. infrahub/api/dependencies.py +6 -6
  2. infrahub/api/diff/validation_models.py +7 -7
  3. infrahub/api/schema.py +1 -1
  4. infrahub/artifacts/models.py +5 -3
  5. infrahub/artifacts/tasks.py +3 -5
  6. infrahub/cli/__init__.py +13 -9
  7. infrahub/cli/constants.py +3 -0
  8. infrahub/cli/db.py +165 -183
  9. infrahub/cli/upgrade.py +146 -0
  10. infrahub/computed_attribute/gather.py +185 -0
  11. infrahub/computed_attribute/models.py +240 -12
  12. infrahub/computed_attribute/tasks.py +77 -441
  13. infrahub/computed_attribute/triggers.py +13 -47
  14. infrahub/config.py +43 -32
  15. infrahub/context.py +14 -0
  16. infrahub/core/account.py +4 -4
  17. infrahub/core/attribute.py +58 -58
  18. infrahub/core/branch/tasks.py +74 -22
  19. infrahub/core/changelog/diff.py +95 -36
  20. infrahub/core/changelog/models.py +217 -43
  21. infrahub/core/constants/__init__.py +28 -0
  22. infrahub/core/constants/infrahubkind.py +2 -0
  23. infrahub/core/constants/schema.py +2 -0
  24. infrahub/core/constraint/node/runner.py +9 -8
  25. infrahub/core/diff/branch_differ.py +10 -10
  26. infrahub/core/diff/enricher/cardinality_one.py +5 -0
  27. infrahub/core/diff/enricher/hierarchy.py +17 -4
  28. infrahub/core/diff/enricher/labels.py +5 -0
  29. infrahub/core/diff/enricher/path_identifier.py +4 -0
  30. infrahub/core/diff/ipam_diff_parser.py +4 -5
  31. infrahub/core/diff/model/diff.py +27 -27
  32. infrahub/core/diff/model/path.py +32 -9
  33. infrahub/core/diff/parent_node_adder.py +78 -0
  34. infrahub/core/diff/payload_builder.py +13 -2
  35. infrahub/core/diff/query/filters.py +2 -2
  36. infrahub/core/diff/query/merge.py +20 -17
  37. infrahub/core/diff/query/save.py +188 -182
  38. infrahub/core/diff/query/summary_counts_enricher.py +51 -4
  39. infrahub/core/diff/query_parser.py +4 -4
  40. infrahub/core/diff/repository/deserializer.py +8 -3
  41. infrahub/core/diff/repository/repository.py +156 -38
  42. infrahub/core/diff/tasks.py +4 -4
  43. infrahub/core/graph/__init__.py +1 -1
  44. infrahub/core/graph/index.py +3 -0
  45. infrahub/core/initialization.py +1 -10
  46. infrahub/core/ipam/constants.py +3 -4
  47. infrahub/core/ipam/reconciler.py +12 -12
  48. infrahub/core/ipam/utilization.py +10 -13
  49. infrahub/core/manager.py +36 -36
  50. infrahub/core/merge.py +7 -7
  51. infrahub/core/migrations/__init__.py +2 -3
  52. infrahub/core/migrations/graph/__init__.py +12 -3
  53. infrahub/core/migrations/graph/m017_add_core_profile.py +1 -5
  54. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +4 -4
  55. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
  56. infrahub/core/migrations/graph/m020_duplicate_edges.py +160 -0
  57. infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +51 -0
  58. infrahub/core/migrations/graph/m022_add_generate_template_attr.py +48 -0
  59. infrahub/core/migrations/graph/m023_deduplicate_cardinality_one_relationships.py +96 -0
  60. infrahub/core/migrations/query/attribute_add.py +2 -2
  61. infrahub/core/migrations/query/node_duplicate.py +43 -26
  62. infrahub/core/migrations/query/schema_attribute_update.py +2 -2
  63. infrahub/core/migrations/schema/models.py +19 -4
  64. infrahub/core/migrations/schema/node_remove.py +26 -12
  65. infrahub/core/migrations/schema/tasks.py +2 -2
  66. infrahub/core/migrations/shared.py +16 -16
  67. infrahub/core/models.py +15 -6
  68. infrahub/core/node/__init__.py +43 -39
  69. infrahub/core/node/base.py +2 -4
  70. infrahub/core/node/constraints/attribute_uniqueness.py +2 -2
  71. infrahub/core/node/constraints/grouped_uniqueness.py +99 -47
  72. infrahub/core/node/constraints/interface.py +1 -2
  73. infrahub/core/node/delete_validator.py +3 -5
  74. infrahub/core/node/ipam.py +4 -4
  75. infrahub/core/node/permissions.py +7 -7
  76. infrahub/core/node/resource_manager/ip_address_pool.py +6 -6
  77. infrahub/core/node/resource_manager/ip_prefix_pool.py +6 -6
  78. infrahub/core/node/resource_manager/number_pool.py +3 -3
  79. infrahub/core/path.py +12 -12
  80. infrahub/core/property.py +11 -11
  81. infrahub/core/protocols.py +7 -0
  82. infrahub/core/protocols_base.py +21 -21
  83. infrahub/core/query/__init__.py +33 -33
  84. infrahub/core/query/attribute.py +6 -4
  85. infrahub/core/query/diff.py +3 -3
  86. infrahub/core/query/node.py +82 -32
  87. infrahub/core/query/relationship.py +228 -40
  88. infrahub/core/query/resource_manager.py +2 -0
  89. infrahub/core/query/standard_node.py +3 -3
  90. infrahub/core/query/subquery.py +9 -9
  91. infrahub/core/registry.py +13 -15
  92. infrahub/core/relationship/constraints/count.py +3 -4
  93. infrahub/core/relationship/constraints/peer_kind.py +3 -4
  94. infrahub/core/relationship/constraints/profiles_kind.py +2 -2
  95. infrahub/core/relationship/model.py +51 -59
  96. infrahub/core/schema/attribute_schema.py +16 -8
  97. infrahub/core/schema/basenode_schema.py +105 -44
  98. infrahub/core/schema/computed_attribute.py +3 -3
  99. infrahub/core/schema/definitions/core/__init__.py +147 -0
  100. infrahub/core/schema/definitions/core/account.py +171 -0
  101. infrahub/core/schema/definitions/core/artifact.py +136 -0
  102. infrahub/core/schema/definitions/core/builtin.py +24 -0
  103. infrahub/core/schema/definitions/core/check.py +68 -0
  104. infrahub/core/schema/definitions/core/core.py +17 -0
  105. infrahub/core/schema/definitions/core/generator.py +100 -0
  106. infrahub/core/schema/definitions/core/graphql_query.py +79 -0
  107. infrahub/core/schema/definitions/core/group.py +108 -0
  108. infrahub/core/schema/definitions/core/ipam.py +193 -0
  109. infrahub/core/schema/definitions/core/lineage.py +19 -0
  110. infrahub/core/schema/definitions/core/menu.py +48 -0
  111. infrahub/core/schema/definitions/core/permission.py +163 -0
  112. infrahub/core/schema/definitions/core/profile.py +18 -0
  113. infrahub/core/schema/definitions/core/propose_change.py +97 -0
  114. infrahub/core/schema/definitions/core/propose_change_comment.py +193 -0
  115. infrahub/core/schema/definitions/core/propose_change_validator.py +328 -0
  116. infrahub/core/schema/definitions/core/repository.py +286 -0
  117. infrahub/core/schema/definitions/core/resource_pool.py +170 -0
  118. infrahub/core/schema/definitions/core/template.py +27 -0
  119. infrahub/core/schema/definitions/core/transform.py +96 -0
  120. infrahub/core/schema/definitions/core/webhook.py +134 -0
  121. infrahub/core/schema/definitions/internal.py +16 -16
  122. infrahub/core/schema/dropdown.py +3 -4
  123. infrahub/core/schema/generated/attribute_schema.py +15 -18
  124. infrahub/core/schema/generated/base_node_schema.py +12 -14
  125. infrahub/core/schema/generated/node_schema.py +3 -5
  126. infrahub/core/schema/generated/relationship_schema.py +9 -11
  127. infrahub/core/schema/generic_schema.py +2 -2
  128. infrahub/core/schema/manager.py +20 -9
  129. infrahub/core/schema/node_schema.py +4 -2
  130. infrahub/core/schema/relationship_schema.py +14 -6
  131. infrahub/core/schema/schema_branch.py +292 -144
  132. infrahub/core/schema/schema_branch_computed.py +41 -4
  133. infrahub/core/task/task.py +3 -3
  134. infrahub/core/task/user_task.py +15 -15
  135. infrahub/core/timestamp.py +3 -3
  136. infrahub/core/utils.py +20 -18
  137. infrahub/core/validators/__init__.py +1 -3
  138. infrahub/core/validators/aggregated_checker.py +2 -2
  139. infrahub/core/validators/attribute/choices.py +2 -2
  140. infrahub/core/validators/attribute/enum.py +2 -2
  141. infrahub/core/validators/attribute/kind.py +2 -2
  142. infrahub/core/validators/attribute/length.py +2 -2
  143. infrahub/core/validators/attribute/optional.py +2 -2
  144. infrahub/core/validators/attribute/regex.py +2 -2
  145. infrahub/core/validators/attribute/unique.py +2 -2
  146. infrahub/core/validators/checks_runner.py +25 -2
  147. infrahub/core/validators/determiner.py +1 -3
  148. infrahub/core/validators/interface.py +6 -2
  149. infrahub/core/validators/model.py +22 -3
  150. infrahub/core/validators/models/validate_migration.py +17 -4
  151. infrahub/core/validators/node/attribute.py +2 -2
  152. infrahub/core/validators/node/generate_profile.py +2 -2
  153. infrahub/core/validators/node/hierarchy.py +3 -5
  154. infrahub/core/validators/node/inherit_from.py +27 -5
  155. infrahub/core/validators/node/relationship.py +2 -2
  156. infrahub/core/validators/relationship/count.py +4 -4
  157. infrahub/core/validators/relationship/optional.py +2 -2
  158. infrahub/core/validators/relationship/peer.py +2 -2
  159. infrahub/core/validators/shared.py +2 -2
  160. infrahub/core/validators/tasks.py +8 -0
  161. infrahub/core/validators/uniqueness/checker.py +22 -21
  162. infrahub/core/validators/uniqueness/index.py +2 -2
  163. infrahub/core/validators/uniqueness/model.py +11 -11
  164. infrahub/database/__init__.py +27 -22
  165. infrahub/database/metrics.py +7 -1
  166. infrahub/dependencies/builder/constraint/grouped/node_runner.py +1 -3
  167. infrahub/dependencies/builder/diff/deserializer.py +3 -1
  168. infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
  169. infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
  170. infrahub/dependencies/component/registry.py +2 -2
  171. infrahub/events/__init__.py +25 -2
  172. infrahub/events/artifact_action.py +64 -0
  173. infrahub/events/branch_action.py +33 -22
  174. infrahub/events/generator.py +71 -0
  175. infrahub/events/group_action.py +51 -21
  176. infrahub/events/models.py +18 -19
  177. infrahub/events/node_action.py +88 -37
  178. infrahub/events/repository_action.py +5 -18
  179. infrahub/events/schema_action.py +4 -9
  180. infrahub/events/utils.py +16 -0
  181. infrahub/events/validator_action.py +55 -0
  182. infrahub/exceptions.py +32 -24
  183. infrahub/generators/models.py +2 -3
  184. infrahub/generators/tasks.py +24 -4
  185. infrahub/git/base.py +7 -7
  186. infrahub/git/integrator.py +48 -24
  187. infrahub/git/models.py +101 -9
  188. infrahub/git/repository.py +3 -3
  189. infrahub/git/tasks.py +408 -6
  190. infrahub/git/utils.py +48 -0
  191. infrahub/git/worktree.py +1 -2
  192. infrahub/git_credential/askpass.py +1 -2
  193. infrahub/graphql/analyzer.py +12 -0
  194. infrahub/graphql/app.py +13 -15
  195. infrahub/graphql/context.py +39 -0
  196. infrahub/graphql/initialization.py +3 -0
  197. infrahub/graphql/loaders/node.py +2 -12
  198. infrahub/graphql/loaders/peers.py +77 -0
  199. infrahub/graphql/loaders/shared.py +13 -0
  200. infrahub/graphql/manager.py +17 -19
  201. infrahub/graphql/mutations/artifact_definition.py +5 -5
  202. infrahub/graphql/mutations/branch.py +26 -1
  203. infrahub/graphql/mutations/computed_attribute.py +9 -5
  204. infrahub/graphql/mutations/diff.py +23 -11
  205. infrahub/graphql/mutations/diff_conflict.py +5 -0
  206. infrahub/graphql/mutations/generator.py +83 -0
  207. infrahub/graphql/mutations/graphql_query.py +5 -5
  208. infrahub/graphql/mutations/ipam.py +54 -74
  209. infrahub/graphql/mutations/main.py +195 -132
  210. infrahub/graphql/mutations/menu.py +7 -7
  211. infrahub/graphql/mutations/models.py +2 -4
  212. infrahub/graphql/mutations/node_getter/by_default_filter.py +10 -10
  213. infrahub/graphql/mutations/node_getter/by_hfid.py +1 -3
  214. infrahub/graphql/mutations/node_getter/by_id.py +1 -3
  215. infrahub/graphql/mutations/node_getter/interface.py +1 -2
  216. infrahub/graphql/mutations/proposed_change.py +7 -7
  217. infrahub/graphql/mutations/relationship.py +93 -19
  218. infrahub/graphql/mutations/repository.py +8 -8
  219. infrahub/graphql/mutations/resource_manager.py +3 -3
  220. infrahub/graphql/mutations/schema.py +19 -4
  221. infrahub/graphql/mutations/webhook.py +137 -0
  222. infrahub/graphql/parser.py +4 -4
  223. infrahub/graphql/permissions.py +1 -10
  224. infrahub/graphql/queries/diff/tree.py +19 -14
  225. infrahub/graphql/queries/event.py +5 -2
  226. infrahub/graphql/queries/ipam.py +2 -2
  227. infrahub/graphql/queries/relationship.py +2 -2
  228. infrahub/graphql/queries/search.py +2 -2
  229. infrahub/graphql/resolvers/many_relationship.py +264 -0
  230. infrahub/graphql/resolvers/resolver.py +13 -110
  231. infrahub/graphql/schema.py +2 -0
  232. infrahub/graphql/subscription/graphql_query.py +2 -0
  233. infrahub/graphql/types/context.py +12 -0
  234. infrahub/graphql/types/event.py +84 -17
  235. infrahub/graphql/types/node.py +2 -2
  236. infrahub/graphql/utils.py +2 -2
  237. infrahub/groups/ancestors.py +29 -0
  238. infrahub/groups/parsers.py +107 -0
  239. infrahub/lock.py +20 -20
  240. infrahub/menu/constants.py +0 -1
  241. infrahub/menu/generator.py +9 -21
  242. infrahub/menu/menu.py +17 -38
  243. infrahub/menu/models.py +117 -16
  244. infrahub/menu/repository.py +111 -0
  245. infrahub/menu/utils.py +5 -8
  246. infrahub/message_bus/__init__.py +11 -13
  247. infrahub/message_bus/messages/__init__.py +1 -21
  248. infrahub/message_bus/messages/check_generator_run.py +3 -3
  249. infrahub/message_bus/messages/finalize_validator_execution.py +3 -0
  250. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +6 -0
  251. infrahub/message_bus/messages/request_generatordefinition_check.py +2 -0
  252. infrahub/message_bus/messages/send_echo_request.py +1 -1
  253. infrahub/message_bus/operations/__init__.py +1 -10
  254. infrahub/message_bus/operations/check/__init__.py +2 -2
  255. infrahub/message_bus/operations/check/generator.py +1 -0
  256. infrahub/message_bus/operations/event/__init__.py +2 -2
  257. infrahub/message_bus/operations/event/worker.py +0 -3
  258. infrahub/message_bus/operations/finalize/validator.py +51 -1
  259. infrahub/message_bus/operations/requests/__init__.py +0 -2
  260. infrahub/message_bus/operations/requests/generator_definition.py +21 -23
  261. infrahub/message_bus/operations/requests/proposed_change.py +14 -10
  262. infrahub/permissions/globals.py +15 -0
  263. infrahub/pools/number.py +2 -4
  264. infrahub/proposed_change/models.py +3 -0
  265. infrahub/proposed_change/tasks.py +58 -45
  266. infrahub/pytest_plugin.py +13 -10
  267. infrahub/server.py +2 -3
  268. infrahub/services/__init__.py +2 -2
  269. infrahub/services/adapters/cache/__init__.py +4 -6
  270. infrahub/services/adapters/cache/nats.py +4 -5
  271. infrahub/services/adapters/cache/redis.py +3 -7
  272. infrahub/services/adapters/event/__init__.py +1 -1
  273. infrahub/services/adapters/message_bus/__init__.py +3 -3
  274. infrahub/services/adapters/message_bus/local.py +2 -2
  275. infrahub/services/adapters/message_bus/nats.py +4 -4
  276. infrahub/services/adapters/message_bus/rabbitmq.py +4 -4
  277. infrahub/services/adapters/workflow/local.py +2 -2
  278. infrahub/services/component.py +5 -5
  279. infrahub/services/protocols.py +7 -7
  280. infrahub/services/scheduler.py +1 -3
  281. infrahub/task_manager/event.py +102 -9
  282. infrahub/task_manager/models.py +27 -7
  283. infrahub/tasks/artifact.py +7 -6
  284. infrahub/telemetry/__init__.py +0 -0
  285. infrahub/telemetry/constants.py +9 -0
  286. infrahub/telemetry/database.py +86 -0
  287. infrahub/telemetry/models.py +65 -0
  288. infrahub/telemetry/task_manager.py +77 -0
  289. infrahub/{tasks/telemetry.py → telemetry/tasks.py} +49 -56
  290. infrahub/telemetry/utils.py +11 -0
  291. infrahub/trace.py +4 -4
  292. infrahub/transformations/tasks.py +2 -2
  293. infrahub/trigger/catalogue.py +4 -6
  294. infrahub/trigger/constants.py +0 -8
  295. infrahub/trigger/models.py +54 -5
  296. infrahub/trigger/setup.py +90 -0
  297. infrahub/trigger/tasks.py +35 -84
  298. infrahub/utils.py +11 -1
  299. infrahub/validators/__init__.py +0 -0
  300. infrahub/validators/events.py +42 -0
  301. infrahub/validators/tasks.py +41 -0
  302. infrahub/webhook/gather.py +17 -0
  303. infrahub/webhook/models.py +176 -44
  304. infrahub/webhook/tasks.py +154 -155
  305. infrahub/webhook/triggers.py +31 -7
  306. infrahub/workers/infrahub_async.py +2 -2
  307. infrahub/workers/utils.py +2 -2
  308. infrahub/workflows/catalogue.py +86 -35
  309. infrahub/workflows/initialization.py +8 -2
  310. infrahub/workflows/models.py +27 -1
  311. infrahub/workflows/utils.py +10 -1
  312. infrahub_sdk/client.py +35 -8
  313. infrahub_sdk/config.py +3 -0
  314. infrahub_sdk/context.py +13 -0
  315. infrahub_sdk/ctl/branch.py +3 -2
  316. infrahub_sdk/ctl/cli_commands.py +5 -1
  317. infrahub_sdk/ctl/utils.py +0 -16
  318. infrahub_sdk/exceptions.py +12 -0
  319. infrahub_sdk/generator.py +4 -1
  320. infrahub_sdk/graphql.py +45 -13
  321. infrahub_sdk/node.py +71 -22
  322. infrahub_sdk/protocols.py +21 -8
  323. infrahub_sdk/protocols_base.py +32 -11
  324. infrahub_sdk/query_groups.py +6 -35
  325. infrahub_sdk/schema/__init__.py +55 -26
  326. infrahub_sdk/schema/main.py +8 -0
  327. infrahub_sdk/task/__init__.py +11 -0
  328. infrahub_sdk/task/constants.py +3 -0
  329. infrahub_sdk/task/exceptions.py +25 -0
  330. infrahub_sdk/task/manager.py +551 -0
  331. infrahub_sdk/task/models.py +74 -0
  332. infrahub_sdk/testing/schemas/animal.py +9 -0
  333. infrahub_sdk/timestamp.py +142 -33
  334. infrahub_sdk/utils.py +29 -1
  335. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/METADATA +8 -6
  336. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/RECORD +349 -293
  337. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/entry_points.txt +1 -0
  338. infrahub_testcontainers/constants.py +2 -0
  339. infrahub_testcontainers/container.py +157 -12
  340. infrahub_testcontainers/docker-compose.test.yml +31 -6
  341. infrahub_testcontainers/helpers.py +18 -73
  342. infrahub_testcontainers/host.py +41 -0
  343. infrahub_testcontainers/measurements.py +93 -0
  344. infrahub_testcontainers/models.py +38 -0
  345. infrahub_testcontainers/performance_test.py +166 -0
  346. infrahub_testcontainers/plugin.py +136 -0
  347. infrahub_testcontainers/prometheus.yml +30 -0
  348. infrahub/core/schema/definitions/core.py +0 -2286
  349. infrahub/message_bus/messages/check_repository_checkdefinition.py +0 -20
  350. infrahub/message_bus/messages/check_repository_mergeconflicts.py +0 -16
  351. infrahub/message_bus/messages/check_repository_usercheck.py +0 -26
  352. infrahub/message_bus/messages/event_branch_create.py +0 -11
  353. infrahub/message_bus/messages/event_branch_delete.py +0 -11
  354. infrahub/message_bus/messages/event_branch_rebased.py +0 -9
  355. infrahub/message_bus/messages/event_node_mutated.py +0 -15
  356. infrahub/message_bus/messages/event_schema_update.py +0 -9
  357. infrahub/message_bus/messages/request_repository_checks.py +0 -12
  358. infrahub/message_bus/messages/request_repository_userchecks.py +0 -18
  359. infrahub/message_bus/operations/check/repository.py +0 -293
  360. infrahub/message_bus/operations/event/node.py +0 -20
  361. infrahub/message_bus/operations/event/schema.py +0 -17
  362. infrahub/message_bus/operations/requests/repository.py +0 -133
  363. infrahub/webhook/constants.py +0 -1
  364. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/LICENSE.txt +0 -0
  365. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/WHEEL +0 -0
@@ -18,10 +18,12 @@ from ..model.path import (
18
18
  EnrichedDiffSingleRelationship,
19
19
  deserialize_tracking_id,
20
20
  )
21
+ from ..parent_node_adder import DiffParentNodeAdder, ParentNodeAddRequest
21
22
 
22
23
 
23
24
  class EnrichedDiffDeserializer:
24
- def __init__(self) -> None:
25
+ def __init__(self, parent_adder: DiffParentNodeAdder) -> None:
26
+ self.parent_adder = parent_adder
25
27
  self._diff_root_map: dict[str, EnrichedDiffRoot] = {}
26
28
  self._diff_node_map: dict[tuple[str, str], EnrichedDiffNode] = {}
27
29
  self._diff_node_attr_map: dict[tuple[str, str, str], EnrichedDiffAttribute] = {}
@@ -127,6 +129,7 @@ class EnrichedDiffDeserializer:
127
129
 
128
130
  def _deserialize_parents(self) -> None:
129
131
  for enriched_root, node_path_tuples in self._parents_path_map.items():
132
+ self.parent_adder.initialize(enriched_diff_root=enriched_root)
130
133
  for node_uuid, parents_path in node_path_tuples:
131
134
  # Remove the node itself from the path
132
135
  parents_path_slice = parents_path.nodes[1:]
@@ -134,7 +137,7 @@ class EnrichedDiffDeserializer:
134
137
  # TODO Ensure the list is even
135
138
  current_node_uuid = node_uuid
136
139
  for rel, parent in zip(parents_path_slice[::2], parents_path_slice[1::2], strict=False):
137
- enriched_root.add_parent(
140
+ parent_request = ParentNodeAddRequest(
138
141
  node_id=current_node_uuid,
139
142
  parent_id=parent.get("uuid"),
140
143
  parent_kind=parent.get("kind"),
@@ -144,6 +147,7 @@ class EnrichedDiffDeserializer:
144
147
  parent_rel_cardinality=RelationshipCardinality(rel.get("cardinality")),
145
148
  parent_rel_label=rel.get("label"),
146
149
  )
150
+ self.parent_adder.add_parent(parent_request=parent_request)
147
151
  current_node_uuid = parent.get("uuid")
148
152
 
149
153
  @classmethod
@@ -164,6 +168,7 @@ class EnrichedDiffDeserializer:
164
168
  def build_diff_root_metadata(cls, root_node: Neo4jNode) -> EnrichedDiffRootMetadata:
165
169
  from_time = Timestamp(str(root_node.get("from_time")))
166
170
  to_time = Timestamp(str(root_node.get("to_time")))
171
+ partner_uuid = cls._get_str_or_none_property_value(node=root_node, property_name="partner_uuid")
167
172
  tracking_id_str = str(root_node.get("tracking_id"))
168
173
  tracking_id = deserialize_tracking_id(tracking_id_str=tracking_id_str)
169
174
  return EnrichedDiffRootMetadata(
@@ -172,7 +177,7 @@ class EnrichedDiffDeserializer:
172
177
  from_time=from_time,
173
178
  to_time=to_time,
174
179
  uuid=str(root_node.get("uuid")),
175
- partner_uuid=str(root_node.get("partner_uuid")),
180
+ partner_uuid=partner_uuid,
176
181
  tracking_id=tracking_id,
177
182
  num_added=int(root_node.get("num_added", 0)),
178
183
  num_updated=int(root_node.get("num_updated", 0)),
@@ -1,10 +1,15 @@
1
1
  from collections import defaultdict
2
2
  from typing import AsyncGenerator, Generator, Iterable
3
3
 
4
+ from neo4j.exceptions import TransientError
5
+
4
6
  from infrahub import config
5
7
  from infrahub.core import registry
6
8
  from infrahub.core.diff.query.field_summary import EnrichedDiffNodeFieldSummaryQuery
7
- from infrahub.core.diff.query.summary_counts_enricher import DiffSummaryCountsEnricherQuery
9
+ from infrahub.core.diff.query.summary_counts_enricher import (
10
+ DiffFieldsSummaryCountsEnricherQuery,
11
+ DiffNodesSummaryCountsEnricherQuery,
12
+ )
8
13
  from infrahub.core.query.diff import DiffCountChanges
9
14
  from infrahub.core.timestamp import Timestamp
10
15
  from infrahub.database import InfrahubDatabase, retry_db_transaction
@@ -14,6 +19,7 @@ from infrahub.log import get_logger
14
19
  from ..model.path import (
15
20
  ConflictSelection,
16
21
  EnrichedDiffConflict,
22
+ EnrichedDiffNode,
17
23
  EnrichedDiffRoot,
18
24
  EnrichedDiffRootMetadata,
19
25
  EnrichedDiffs,
@@ -42,11 +48,10 @@ log = get_logger()
42
48
 
43
49
 
44
50
  class DiffRepository:
45
- MAX_SAVE_BATCH_SIZE: int = 100
46
-
47
- def __init__(self, db: InfrahubDatabase, deserializer: EnrichedDiffDeserializer):
51
+ def __init__(self, db: InfrahubDatabase, deserializer: EnrichedDiffDeserializer, max_save_batch_size: int = 1000):
48
52
  self.db = db
49
53
  self.deserializer = deserializer
54
+ self.max_save_batch_size = max_save_batch_size
50
55
 
51
56
  async def _run_get_diff_query(
52
57
  self,
@@ -154,18 +159,23 @@ class DiffRepository:
154
159
  diff_branch_names=[base_branch_name],
155
160
  max_depth=max_depth,
156
161
  batch_size_limit=batch_size_limit,
157
- diff_ids=[d.partner_uuid for d in diffs_by_uuid.values()],
162
+ diff_ids=[d.partner_uuid for d in diffs_by_uuid.values() if d.partner_uuid],
158
163
  )
159
164
  diffs_by_uuid.update({bbr.uuid: bbr for bbr in base_branch_roots})
160
- return [
161
- EnrichedDiffs(
162
- base_branch_name=base_branch_name,
163
- diff_branch_name=diff_branch_name,
164
- base_branch_diff=diffs_by_uuid[dbr.partner_uuid],
165
- diff_branch_diff=dbr,
165
+ diff_pairs = []
166
+ for dbr in diff_branch_roots:
167
+ if dbr.partner_uuid is None:
168
+ continue
169
+ base_branch_diff = diffs_by_uuid[dbr.partner_uuid]
170
+ diff_pairs.append(
171
+ EnrichedDiffs(
172
+ base_branch_name=base_branch_name,
173
+ diff_branch_name=diff_branch_name,
174
+ base_branch_diff=base_branch_diff,
175
+ diff_branch_diff=dbr,
176
+ )
166
177
  )
167
- for dbr in diff_branch_roots
168
- ]
178
+ return diff_pairs
169
179
 
170
180
  async def hydrate_diff_pair(
171
181
  self,
@@ -225,43 +235,111 @@ class DiffRepository:
225
235
  ) -> Generator[list[EnrichedNodeCreateRequest], None, None]:
226
236
  node_requests = []
227
237
  for diff_root in (enriched_diffs.base_branch_diff, enriched_diffs.diff_branch_diff):
238
+ size_count = 0
228
239
  for node in diff_root.nodes:
229
- node_requests.append(EnrichedNodeCreateRequest(node=node, root_uuid=diff_root.uuid))
230
- if len(node_requests) == self.MAX_SAVE_BATCH_SIZE:
240
+ node_size_count = node.num_properties
241
+ if size_count + node_size_count < self.max_save_batch_size:
242
+ node_requests.append(EnrichedNodeCreateRequest(node=node, root_uuid=diff_root.uuid))
243
+ size_count += node_size_count
244
+ else:
245
+ log.info(f"Num nodes in batch: {len(node_requests)}, num properties in batch: {size_count}")
231
246
  yield node_requests
232
- node_requests = []
247
+ size_count = node_size_count
248
+ node_requests = [EnrichedNodeCreateRequest(node=node, root_uuid=diff_root.uuid)]
233
249
  if node_requests:
250
+ log.info(f"Num nodes in batch: {len(node_requests)}, num properties in batch: {size_count}")
234
251
  yield node_requests
235
252
 
236
- @retry_db_transaction(name="enriched_diff_save")
237
- async def save(self, enriched_diffs: EnrichedDiffs | EnrichedDiffsMetadata, do_summary_counts: bool = True) -> None:
253
+ @retry_db_transaction(name="enriched_diff_metadata_save")
254
+ async def _save_root_metadata(self, enriched_diffs: EnrichedDiffsMetadata) -> None:
238
255
  log.info("Updating diff metadata...")
239
256
  root_query = await EnrichedDiffRootsUpsertQuery.init(db=self.db, enriched_diffs=enriched_diffs)
240
257
  await root_query.execute(db=self.db)
241
258
  log.info("Diff metadata updated.")
259
+
260
+ async def _save_node_batch(self, node_create_batch: list[EnrichedNodeCreateRequest]) -> None:
261
+ node_query = await EnrichedNodeBatchCreateQuery.init(db=self.db, node_create_batch=node_create_batch)
262
+ try:
263
+ await node_query.execute(db=self.db)
264
+ except TransientError as exc:
265
+ if not exc.code or "OutOfMemoryError".lower() not in str(exc.code).lower():
266
+ raise
267
+ log.exception("Database memory error during save. Trying smaller transactions")
268
+ for node_request in node_create_batch:
269
+ log.info(
270
+ f"Updating node {node_request.node.uuid}, num_properties={node_request.node.num_properties}..."
271
+ )
272
+ single_node_query = await EnrichedNodeBatchCreateQuery.init(
273
+ db=self.db, node_create_batch=[node_request]
274
+ )
275
+ await single_node_query.execute(db=self.db)
276
+
277
+ @retry_db_transaction(name="enriched_diff_hierarchy_update")
278
+ async def _run_hierarchy_links_update_query(self, diff_root_uuid: str, diff_nodes: list[EnrichedDiffNode]) -> None:
279
+ log.info(f"Updating diff hierarchy links, num_nodes={len(diff_nodes)}")
280
+ link_query = await EnrichedNodesLinkQuery.init(db=self.db, diff_root_uuid=diff_root_uuid, diff_nodes=diff_nodes)
281
+ await link_query.execute(db=self.db)
282
+
283
+ async def _update_hierarchy_links(self, enriched_diffs: EnrichedDiffs) -> None:
284
+ for diff_root in (enriched_diffs.base_branch_diff, enriched_diffs.diff_branch_diff):
285
+ nodes_to_update = []
286
+ for node in diff_root.nodes:
287
+ if any(r.nodes for r in node.relationships):
288
+ nodes_to_update.append(node)
289
+ if len(nodes_to_update) >= config.SETTINGS.database.query_size_limit:
290
+ await self._run_hierarchy_links_update_query(
291
+ diff_root_uuid=diff_root.uuid, diff_nodes=nodes_to_update
292
+ )
293
+ nodes_to_update = []
294
+ if nodes_to_update:
295
+ await self._run_hierarchy_links_update_query(diff_root_uuid=diff_root.uuid, diff_nodes=nodes_to_update)
296
+
297
+ async def _update_summary_counts(self, diff_root: EnrichedDiffRoot) -> None:
298
+ max_nodes_limit = config.SETTINGS.database.query_size_limit
299
+ num_nodes = len(diff_root.nodes)
300
+ if diff_root.exists_on_database and num_nodes < max_nodes_limit:
301
+ await self.add_summary_counts(
302
+ diff_branch_name=diff_root.diff_branch_name,
303
+ diff_id=diff_root.uuid,
304
+ node_uuids=None,
305
+ )
306
+ return
307
+ node_uuids: list[str] = []
308
+ for diff_node in diff_root.nodes:
309
+ node_uuids.append(diff_node.uuid)
310
+ if len(node_uuids) >= max_nodes_limit:
311
+ await self.add_summary_counts(
312
+ diff_branch_name=diff_root.diff_branch_name,
313
+ diff_id=diff_root.uuid,
314
+ node_uuids=node_uuids,
315
+ )
316
+ node_uuids = []
317
+ if node_uuids:
318
+ await self.add_summary_counts(
319
+ diff_branch_name=diff_root.diff_branch_name,
320
+ diff_id=diff_root.uuid,
321
+ node_uuids=node_uuids,
322
+ )
323
+
324
+ async def save(self, enriched_diffs: EnrichedDiffs | EnrichedDiffsMetadata, do_summary_counts: bool = True) -> None:
325
+ # metadata-only update
242
326
  if not isinstance(enriched_diffs, EnrichedDiffs):
327
+ await self._save_root_metadata(enriched_diffs=enriched_diffs)
243
328
  return
244
- num_nodes = len(enriched_diffs.base_branch_diff.nodes) + len(enriched_diffs.diff_branch_diff.nodes)
245
- log.info(f"Saving diff (num_nodes={num_nodes})...")
329
+
330
+ count_nodes_remaining = len(enriched_diffs.base_branch_diff.nodes) + len(enriched_diffs.diff_branch_diff.nodes)
331
+ log.info(f"Saving diff (num_nodes={count_nodes_remaining})...")
246
332
  for batch_num, node_create_batch in enumerate(
247
333
  self._get_node_create_request_batch(enriched_diffs=enriched_diffs)
248
334
  ):
249
335
  log.info(f"Saving node batch #{batch_num}...")
250
- node_query = await EnrichedNodeBatchCreateQuery.init(db=self.db, node_create_batch=node_create_batch)
251
- await node_query.execute(db=self.db)
252
- log.info(f"Batch #{batch_num} saved")
253
- link_query = await EnrichedNodesLinkQuery.init(db=self.db, enriched_diffs=enriched_diffs)
254
- await link_query.execute(db=self.db)
255
- log.info("Diff saved.")
336
+ await self._save_node_batch(node_create_batch=node_create_batch)
337
+ count_nodes_remaining -= len(node_create_batch)
338
+ log.info(f"Batch saved. {count_nodes_remaining=}")
339
+ await self._update_hierarchy_links(enriched_diffs=enriched_diffs)
256
340
  if do_summary_counts:
257
- node_uuids: list[str] | None = None
258
- if enriched_diffs.diff_branch_diff.exists_on_database:
259
- node_uuids = list(enriched_diffs.branch_node_uuids)
260
- await self.add_summary_counts(
261
- diff_branch_name=enriched_diffs.diff_branch_name,
262
- diff_id=enriched_diffs.diff_branch_diff.uuid,
263
- node_uuids=node_uuids,
264
- )
341
+ await self._update_summary_counts(diff_root=enriched_diffs.diff_branch_diff)
342
+ await self._save_root_metadata(enriched_diffs=enriched_diffs)
265
343
 
266
344
  async def summary(
267
345
  self,
@@ -325,7 +403,7 @@ class DiffRepository:
325
403
  roots_by_id = {root.uuid: root for root in empty_roots}
326
404
  pairs: list[EnrichedDiffsMetadata] = []
327
405
  for branch_root in empty_roots:
328
- if branch_root.base_branch_name == branch_root.diff_branch_name:
406
+ if branch_root.base_branch_name == branch_root.diff_branch_name or branch_root.partner_uuid is None:
329
407
  continue
330
408
  base_root = roots_by_id[branch_root.partner_uuid]
331
409
  pairs.append(
@@ -446,8 +524,48 @@ class DiffRepository:
446
524
  diff_id: str | None = None,
447
525
  node_uuids: list[str] | None = None,
448
526
  ) -> None:
449
- log.info("Updating summary counts...")
450
- query = await DiffSummaryCountsEnricherQuery.init(
527
+ await self._add_field_summary_counts(
528
+ diff_branch_name=diff_branch_name,
529
+ tracking_id=tracking_id,
530
+ diff_id=diff_id,
531
+ node_uuids=node_uuids,
532
+ )
533
+ await self._add_node_summary_counts(
534
+ diff_branch_name=diff_branch_name,
535
+ tracking_id=tracking_id,
536
+ diff_id=diff_id,
537
+ node_uuids=node_uuids,
538
+ )
539
+
540
+ @retry_db_transaction(name="enriched_diff_field_summary_counts")
541
+ async def _add_field_summary_counts(
542
+ self,
543
+ diff_branch_name: str,
544
+ tracking_id: TrackingId | None = None,
545
+ diff_id: str | None = None,
546
+ node_uuids: list[str] | None = None,
547
+ ) -> None:
548
+ log.info("Updating field summary counts...")
549
+ query = await DiffFieldsSummaryCountsEnricherQuery.init(
550
+ db=self.db,
551
+ diff_branch_name=diff_branch_name,
552
+ tracking_id=tracking_id,
553
+ diff_id=diff_id,
554
+ node_uuids=node_uuids,
555
+ )
556
+ await query.execute(db=self.db)
557
+ log.info("Field summary counts updated.")
558
+
559
+ @retry_db_transaction(name="enriched_diff_node_summary_counts")
560
+ async def _add_node_summary_counts(
561
+ self,
562
+ diff_branch_name: str,
563
+ tracking_id: TrackingId | None = None,
564
+ diff_id: str | None = None,
565
+ node_uuids: list[str] | None = None,
566
+ ) -> None:
567
+ log.info("Updating node summary counts...")
568
+ query = await DiffNodesSummaryCountsEnricherQuery.init(
451
569
  db=self.db,
452
570
  diff_branch_name=diff_branch_name,
453
571
  tracking_id=tracking_id,
@@ -455,4 +573,4 @@ class DiffRepository:
455
573
  node_uuids=node_uuids,
456
574
  )
457
575
  await query.execute(db=self.db)
458
- log.info("Summary counts updated...")
576
+ log.info("node summary counts updated.")
@@ -11,14 +11,14 @@ from infrahub.dependencies.registry import get_component_registry
11
11
  from infrahub.log import get_logger
12
12
  from infrahub.services import InfrahubServices # noqa: TC001 needed for prefect flow
13
13
  from infrahub.workflows.catalogue import DIFF_REFRESH
14
- from infrahub.workflows.utils import add_branch_tag
14
+ from infrahub.workflows.utils import add_tags
15
15
 
16
16
  log = get_logger()
17
17
 
18
18
 
19
19
  @flow(name="diff-update", flow_run_name="Update diff for branch {model.branch_name}")
20
20
  async def update_diff(model: RequestDiffUpdate, service: InfrahubServices) -> None:
21
- await add_branch_tag(branch_name=model.branch_name)
21
+ await add_tags(branches=[model.branch_name])
22
22
 
23
23
  async with service.database.start_session() as db:
24
24
  component_registry = get_component_registry()
@@ -38,7 +38,7 @@ async def update_diff(model: RequestDiffUpdate, service: InfrahubServices) -> No
38
38
 
39
39
  @flow(name="diff-refresh", flow_run_name="Recreate diff for branch {branch_name}")
40
40
  async def refresh_diff(branch_name: str, diff_id: str, service: InfrahubServices) -> None:
41
- await add_branch_tag(branch_name=branch_name)
41
+ await add_tags(branches=[branch_name])
42
42
 
43
43
  async with service.database.start_session() as db:
44
44
  component_registry = get_component_registry()
@@ -51,7 +51,7 @@ async def refresh_diff(branch_name: str, diff_id: str, service: InfrahubServices
51
51
 
52
52
  @flow(name="diff-refresh-all", flow_run_name="Recreate all diffs for branch {branch_name}")
53
53
  async def refresh_diff_all(branch_name: str, context: InfrahubContext, service: InfrahubServices) -> None:
54
- await add_branch_tag(branch_name=branch_name)
54
+ await add_tags(branches=[branch_name])
55
55
 
56
56
  async with service.database.start_session() as db:
57
57
  component_registry = get_component_registry()
@@ -1 +1 @@
1
- GRAPH_VERSION = 18
1
+ GRAPH_VERSION = 22
@@ -12,6 +12,9 @@ node_indexes: list[IndexItem] = [
12
12
  IndexItem(name="attr_iphost_bin", label="AttributeIPHost", properties=["binary_address"], type=IndexType.RANGE),
13
13
  IndexItem(name="rel_uuid", label="Relationship", properties=["uuid"], type=IndexType.RANGE),
14
14
  IndexItem(name="rel_identifier", label="Relationship", properties=["name"], type=IndexType.RANGE),
15
+ # diff indices
16
+ IndexItem(name="diff_uuid", label="DiffRoot", properties=["uuid"], type=IndexType.TEXT),
17
+ IndexItem(name="diff_node_uuid", label="DiffNode", properties=["uuid"], type=IndexType.TEXT),
15
18
  ]
16
19
 
17
20
  rel_indexes: list[IndexItem] = [
@@ -28,8 +28,7 @@ from infrahub.database import InfrahubDatabase
28
28
  from infrahub.exceptions import DatabaseError
29
29
  from infrahub.graphql.manager import GraphQLSchemaManager
30
30
  from infrahub.log import get_logger
31
- from infrahub.menu.menu import default_menu
32
- from infrahub.menu.utils import create_menu_children
31
+ from infrahub.menu.utils import create_default_menu
33
32
  from infrahub.permissions import PermissionBackend
34
33
  from infrahub.storage import InfrahubObjectStorage
35
34
 
@@ -305,14 +304,6 @@ async def create_ipam_namespace(
305
304
  return obj
306
305
 
307
306
 
308
- async def create_default_menu(db: InfrahubDatabase) -> None:
309
- for item in default_menu:
310
- obj = await item.to_node(db=db)
311
- await obj.save(db=db)
312
- if item.children:
313
- await create_menu_children(db=db, parent=obj, children=item.children)
314
-
315
-
316
307
  async def create_super_administrator_role(db: InfrahubDatabase) -> Node:
317
308
  permission = await Node.init(db=db, schema=InfrahubKind.GLOBALPERMISSION)
318
309
  await permission.new(
@@ -1,10 +1,9 @@
1
1
  import ipaddress
2
2
  from enum import Enum
3
- from typing import Union
4
3
 
5
- IPNetworkType = Union[ipaddress.IPv6Network, ipaddress.IPv4Network]
6
- IPAddressType = Union[ipaddress.IPv6Interface, ipaddress.IPv4Interface]
7
- AllIPTypes = Union[IPNetworkType, IPAddressType]
4
+ IPNetworkType = ipaddress.IPv6Network | ipaddress.IPv4Network
5
+ IPAddressType = ipaddress.IPv6Interface | ipaddress.IPv4Interface
6
+ AllIPTypes = IPNetworkType | IPAddressType
8
7
 
9
8
 
10
9
  class PrefixMemberType(Enum):
@@ -1,5 +1,5 @@
1
1
  import ipaddress
2
- from typing import TYPE_CHECKING, Optional, Union
2
+ from typing import TYPE_CHECKING
3
3
 
4
4
  from infrahub.core.branch import Branch
5
5
  from infrahub.core.constants import InfrahubKind
@@ -20,8 +20,8 @@ class IPNodesToReconcile:
20
20
  def __init__(
21
21
  self,
22
22
  node_uuid: str,
23
- current_parent_uuid: Optional[str],
24
- calculated_parent_uuid: Optional[str],
23
+ current_parent_uuid: str | None,
24
+ calculated_parent_uuid: str | None,
25
25
  current_child_uuids: set[str],
26
26
  calculated_child_uuids: set[str],
27
27
  node_map: dict[str, Node],
@@ -46,13 +46,13 @@ class IPNodesToReconcile:
46
46
  return self.node_map[self.node_uuid]
47
47
 
48
48
  @property
49
- def current_parent(self) -> Optional[Node]:
49
+ def current_parent(self) -> Node | None:
50
50
  if not self.current_parent_uuid:
51
51
  return None
52
52
  return self.node_map.get(self.current_parent_uuid)
53
53
 
54
54
  @property
55
- def calculated_parent(self) -> Optional[Node]:
55
+ def calculated_parent(self) -> Node | None:
56
56
  if not self.calculated_parent_uuid:
57
57
  return None
58
58
  return self.node_map.get(self.calculated_parent_uuid)
@@ -68,7 +68,7 @@ class IPNodesToReconcile:
68
68
  def get_node_by_uuid(self, uuid: str) -> Node:
69
69
  return self.node_map[uuid]
70
70
 
71
- async def _get_child_uuids(self, db: InfrahubDatabase, node: Optional[Node]) -> set[str]:
71
+ async def _get_child_uuids(self, db: InfrahubDatabase, node: Node | None) -> set[str]:
72
72
  if not node:
73
73
  return set()
74
74
  child_uuids = set()
@@ -83,17 +83,17 @@ class IpamReconciler:
83
83
  def __init__(self, db: InfrahubDatabase, branch: Branch) -> None:
84
84
  self.db = db
85
85
  self.branch = branch
86
- self.at: Optional[Timestamp] = None
86
+ self.at: Timestamp | None = None
87
87
 
88
88
  @retry_db_transaction(name="ipam_reconcile")
89
89
  async def reconcile(
90
90
  self,
91
91
  ip_value: AllIPTypes,
92
- namespace: Optional[Union[Node, str]] = None,
93
- node_uuid: Optional[str] = None,
92
+ namespace: Node | str | None = None,
93
+ node_uuid: str | None = None,
94
94
  is_delete: bool = False,
95
- at: Optional[Timestamp] = None,
96
- ) -> Optional[Node]:
95
+ at: Timestamp | None = None,
96
+ ) -> Node | None:
97
97
  self.at = Timestamp(at)
98
98
 
99
99
  query = await IPPrefixReconcileQuery.init(
@@ -152,7 +152,7 @@ class IpamReconciler:
152
152
 
153
153
  return reconcile_nodes.node
154
154
 
155
- async def _update_node_parent(self, node: Node, new_parent_uuid: Optional[str]) -> None:
155
+ async def _update_node_parent(self, node: Node, new_parent_uuid: str | None) -> None:
156
156
  node_kinds = {node.get_kind()} | set(node.get_schema().inherit_from)
157
157
  is_prefix = False
158
158
  if InfrahubKind.IPADDRESS in node_kinds:
@@ -1,5 +1,4 @@
1
1
  from dataclasses import dataclass
2
- from typing import Optional, Union
3
2
 
4
3
  from infrahub.core.constants import InfrahubKind
5
4
  from infrahub.core.node import Node
@@ -19,9 +18,7 @@ class PrefixChildDetails:
19
18
 
20
19
 
21
20
  class PrefixUtilizationGetter:
22
- def __init__(
23
- self, db: InfrahubDatabase, ip_prefixes: list[Node], at: Optional[Union[Timestamp, str]] = None
24
- ) -> None:
21
+ def __init__(self, db: InfrahubDatabase, ip_prefixes: list[Node], at: Timestamp | str | None = None) -> None:
25
22
  self.db = db
26
23
  self.ip_prefixes = ip_prefixes
27
24
  self.at = at
@@ -66,9 +63,9 @@ class PrefixUtilizationGetter:
66
63
 
67
64
  async def get_children(
68
65
  self,
69
- ip_prefixes: Optional[list[Node]] = None,
70
- prefix_member_type: Optional[PrefixMemberType] = None,
71
- branch_names: Optional[list[str]] = None,
66
+ ip_prefixes: list[Node] | None = None,
67
+ prefix_member_type: PrefixMemberType | None = None,
68
+ branch_names: list[str] | None = None,
72
69
  ) -> list[PrefixChildDetails]:
73
70
  await self._fetch_data()
74
71
  prefix_child_details_list: list[PrefixChildDetails] = []
@@ -90,9 +87,9 @@ class PrefixUtilizationGetter:
90
87
 
91
88
  async def get_num_children_in_use(
92
89
  self,
93
- ip_prefixes: Optional[list[Node]] = None,
94
- prefix_member_type: Optional[PrefixMemberType] = None,
95
- branch_names: Optional[list[str]] = None,
90
+ ip_prefixes: list[Node] | None = None,
91
+ prefix_member_type: PrefixMemberType | None = None,
92
+ branch_names: list[str] | None = None,
96
93
  ) -> int:
97
94
  children = await self.get_children(
98
95
  ip_prefixes=ip_prefixes, prefix_member_type=prefix_member_type, branch_names=branch_names
@@ -100,7 +97,7 @@ class PrefixUtilizationGetter:
100
97
  return len(children)
101
98
 
102
99
  async def _get_prefix_use_fraction(
103
- self, ip_prefixes: Optional[list[Node]] = None, branch_names: Optional[list[str]] = None
100
+ self, ip_prefixes: list[Node] | None = None, branch_names: list[str] | None = None
104
101
  ) -> tuple[int, int]:
105
102
  total_prefix_space = 0
106
103
  total_used_space = 0
@@ -117,7 +114,7 @@ class PrefixUtilizationGetter:
117
114
  return total_used_space, total_prefix_space
118
115
 
119
116
  async def _get_address_use_fraction(
120
- self, ip_prefixes: Optional[list[Node]] = None, branch_names: Optional[list[str]] = None
117
+ self, ip_prefixes: list[Node] | None = None, branch_names: list[str] | None = None
121
118
  ) -> tuple[int, int]:
122
119
  total_prefix_space = 0
123
120
  if ip_prefixes is None:
@@ -130,7 +127,7 @@ class PrefixUtilizationGetter:
130
127
  return total_used_space, total_prefix_space
131
128
 
132
129
  async def get_use_percentage(
133
- self, ip_prefixes: Optional[list[Node]] = None, branch_names: Optional[list[str]] = None
130
+ self, ip_prefixes: list[Node] | None = None, branch_names: list[str] | None = None
134
131
  ) -> float:
135
132
  grand_total_used, grand_total_space = 0, 0
136
133
  address_prefixes, prefix_prefixes = [], []