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
@@ -19,7 +19,6 @@ class InfrahubGroupContextBase:
19
19
  self.related_node_ids: list[str] = []
20
20
  self.related_group_ids: list[str] = []
21
21
  self.unused_member_ids: list[str] | None = None
22
- self.unused_child_ids: list[str] | None = None
23
22
  self.previous_members: list[RelatedNodeBase] | None = None
24
23
  self.previous_children: list[RelatedNodeBase] | None = None
25
24
  self.identifier: str | None = None
@@ -88,7 +87,7 @@ class InfrahubGroupContext(InfrahubGroupContextBase):
88
87
  async def get_group(self, store_peers: bool = False) -> InfrahubNode | None:
89
88
  group_name = self._generate_group_name()
90
89
  try:
91
- group = await self.client.get(kind=self.group_type, name__value=group_name, include=["members", "children"])
90
+ group = await self.client.get(kind=self.group_type, name__value=group_name, include=["members"])
92
91
  except NodeNotFoundError:
93
92
  return None
94
93
 
@@ -96,7 +95,6 @@ class InfrahubGroupContext(InfrahubGroupContextBase):
96
95
  return group
97
96
 
98
97
  self.previous_members = group.members.peers # type: ignore[attr-defined]
99
- self.previous_children = group.children.peers # type: ignore[attr-defined]
100
98
  return group
101
99
 
102
100
  async def delete_unused(self) -> None:
@@ -105,11 +103,6 @@ class InfrahubGroupContext(InfrahubGroupContextBase):
105
103
  if member.id in self.unused_member_ids and member.typename:
106
104
  await self.client.delete(kind=member.typename, id=member.id)
107
105
 
108
- if self.previous_children and self.unused_child_ids:
109
- for child in self.previous_children:
110
- if child.id in self.unused_child_ids and child.typename:
111
- await self.client.delete(kind=child.typename, id=child.id)
112
-
113
106
  async def add_related_nodes(self, ids: list[str], update_group_context: bool | None = None) -> None:
114
107
  """
115
108
  Add related Nodes IDs to the context.
@@ -140,15 +133,9 @@ class InfrahubGroupContext(InfrahubGroupContextBase):
140
133
  """
141
134
  Create or update (using upsert) a CoreStandardGroup to store all the Nodes and Groups used during an execution.
142
135
  """
143
- children: list[str] = []
144
- members: list[str] = []
145
-
146
- if self.related_group_ids:
147
- children = self.related_group_ids
148
- if self.related_node_ids:
149
- members = self.related_node_ids
136
+ members: list[str] = self.related_group_ids + self.related_node_ids
150
137
 
151
- if not children and not members:
138
+ if not members:
152
139
  return
153
140
 
154
141
  group_name = self._generate_group_name()
@@ -164,7 +151,6 @@ class InfrahubGroupContext(InfrahubGroupContextBase):
164
151
  name=group_name,
165
152
  description=description,
166
153
  members=members,
167
- children=children,
168
154
  )
169
155
  await group.save(allow_upsert=True, update_group_context=False)
170
156
 
@@ -173,7 +159,6 @@ class InfrahubGroupContext(InfrahubGroupContextBase):
173
159
 
174
160
  # Calculate how many nodes should be deleted
175
161
  self.unused_member_ids = set(existing_group.members.peer_ids) - set(members) # type: ignore
176
- self.unused_child_ids = set(existing_group.children.peer_ids) - set(children) # type: ignore
177
162
 
178
163
  if not self.delete_unused_nodes:
179
164
  return
@@ -194,7 +179,7 @@ class InfrahubGroupContextSync(InfrahubGroupContextBase):
194
179
  def get_group(self, store_peers: bool = False) -> InfrahubNodeSync | None:
195
180
  group_name = self._generate_group_name()
196
181
  try:
197
- group = self.client.get(kind=self.group_type, name__value=group_name, include=["members", "children"])
182
+ group = self.client.get(kind=self.group_type, name__value=group_name, include=["members"])
198
183
  except NodeNotFoundError:
199
184
  return None
200
185
 
@@ -202,7 +187,6 @@ class InfrahubGroupContextSync(InfrahubGroupContextBase):
202
187
  return group
203
188
 
204
189
  self.previous_members = group.members.peers # type: ignore[attr-defined]
205
- self.previous_children = group.children.peers # type: ignore[attr-defined]
206
190
  return group
207
191
 
208
192
  def delete_unused(self) -> None:
@@ -211,11 +195,6 @@ class InfrahubGroupContextSync(InfrahubGroupContextBase):
211
195
  if member.id in self.unused_member_ids and member.typename:
212
196
  self.client.delete(kind=member.typename, id=member.id)
213
197
 
214
- if self.previous_children and self.unused_child_ids:
215
- for child in self.previous_children:
216
- if child.id in self.unused_child_ids and child.typename:
217
- self.client.delete(kind=child.typename, id=child.id)
218
-
219
198
  def add_related_nodes(self, ids: list[str], update_group_context: bool | None = None) -> None:
220
199
  """
221
200
  Add related Nodes IDs to the context.
@@ -246,15 +225,9 @@ class InfrahubGroupContextSync(InfrahubGroupContextBase):
246
225
  """
247
226
  Create or update (using upsert) a CoreStandardGroup to store all the Nodes and Groups used during an execution.
248
227
  """
249
- children: list[str] = []
250
- members: list[str] = []
251
-
252
- if self.related_group_ids:
253
- children = self.related_group_ids
254
- if self.related_node_ids:
255
- members = self.related_node_ids
228
+ members: list[str] = self.related_node_ids + self.related_group_ids
256
229
 
257
- if not children and not members:
230
+ if not members:
258
231
  return
259
232
 
260
233
  group_name = self._generate_group_name()
@@ -270,7 +243,6 @@ class InfrahubGroupContextSync(InfrahubGroupContextBase):
270
243
  name=group_name,
271
244
  description=description,
272
245
  members=members,
273
- children=children,
274
246
  )
275
247
  group.save(allow_upsert=True, update_group_context=False)
276
248
 
@@ -279,7 +251,6 @@ class InfrahubGroupContextSync(InfrahubGroupContextBase):
279
251
 
280
252
  # Calculate how many nodes should be deleted
281
253
  self.unused_member_ids = set(existing_group.members.peer_ids) - set(members) # type: ignore
282
- self.unused_child_ids = set(existing_group.children.peer_ids) - set(children) # type: ignore
283
254
 
284
255
  if not self.delete_unused_nodes:
285
256
  return
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
- from collections import defaultdict
5
4
  from collections.abc import MutableMapping
6
5
  from enum import Enum
7
6
  from time import sleep
@@ -22,6 +21,7 @@ from ..queries import SCHEMA_HASH_SYNC_STATUS
22
21
  from .main import (
23
22
  AttributeSchema,
24
23
  AttributeSchemaAPI,
24
+ BranchSchema,
25
25
  BranchSupportType,
26
26
  GenericSchema,
27
27
  GenericSchemaAPI,
@@ -169,7 +169,7 @@ class InfrahubSchemaBase:
169
169
  class InfrahubSchema(InfrahubSchemaBase):
170
170
  def __init__(self, client: InfrahubClient):
171
171
  self.client = client
172
- self.cache: dict = defaultdict(lambda: dict)
172
+ self.cache: dict[str, BranchSchema] = {}
173
173
 
174
174
  async def get(
175
175
  self,
@@ -183,23 +183,27 @@ class InfrahubSchema(InfrahubSchemaBase):
183
183
  kind_str = self._get_schema_name(schema=kind)
184
184
 
185
185
  if refresh:
186
- self.cache[branch] = await self.fetch(branch=branch, timeout=timeout)
186
+ self.cache[branch] = await self._fetch(branch=branch, timeout=timeout)
187
187
 
188
- if branch in self.cache and kind_str in self.cache[branch]:
189
- return self.cache[branch][kind_str]
188
+ if branch in self.cache and kind_str in self.cache[branch].nodes:
189
+ return self.cache[branch].nodes[kind_str]
190
190
 
191
191
  # Fetching the latest schema from the server if we didn't fetch it earlier
192
192
  # because we coulnd't find the object on the local cache
193
193
  if not refresh:
194
- self.cache[branch] = await self.fetch(branch=branch, timeout=timeout)
194
+ self.cache[branch] = await self._fetch(branch=branch, timeout=timeout)
195
195
 
196
- if branch in self.cache and kind_str in self.cache[branch]:
197
- return self.cache[branch][kind_str]
196
+ if branch in self.cache and kind_str in self.cache[branch].nodes:
197
+ return self.cache[branch].nodes[kind_str]
198
198
 
199
199
  raise SchemaNotFoundError(identifier=kind_str)
200
200
 
201
201
  async def all(
202
- self, branch: str | None = None, refresh: bool = False, namespaces: list[str] | None = None
202
+ self,
203
+ branch: str | None = None,
204
+ refresh: bool = False,
205
+ namespaces: list[str] | None = None,
206
+ schema_hash: str | None = None,
203
207
  ) -> MutableMapping[str, MainSchemaTypesAPI]:
204
208
  """Retrieve the entire schema for a given branch.
205
209
 
@@ -209,15 +213,19 @@ class InfrahubSchema(InfrahubSchemaBase):
209
213
  Args:
210
214
  branch (str, optional): Name of the branch to query. Defaults to default_branch.
211
215
  refresh (bool, optional): Force a refresh of the schema. Defaults to False.
216
+ schema_hash (str, optional): Only refresh if the current schema doesn't match this hash.
212
217
 
213
218
  Returns:
214
219
  dict[str, MainSchemaTypes]: Dictionary of all schema organized by kind
215
220
  """
216
221
  branch = branch or self.client.default_branch
222
+ if refresh and branch in self.cache and schema_hash and self.cache[branch].hash == schema_hash:
223
+ refresh = False
224
+
217
225
  if refresh or branch not in self.cache:
218
- self.cache[branch] = await self.fetch(branch=branch, namespaces=namespaces)
226
+ self.cache[branch] = await self._fetch(branch=branch, namespaces=namespaces)
219
227
 
220
- return self.cache[branch]
228
+ return self.cache[branch].nodes
221
229
 
222
230
  async def load(
223
231
  self, schemas: list[dict], branch: str | None = None, wait_until_converged: bool = False
@@ -392,11 +400,17 @@ class InfrahubSchema(InfrahubSchemaBase):
392
400
 
393
401
  Args:
394
402
  branch (str): Name of the branch to fetch the schema for.
395
- timeout (int, optional): Overrides default timeout used when querying the graphql API. Specified in seconds.
403
+ timeout (int, optional): Overrides default timeout used when querying the GraphQL API. Specified in seconds.
396
404
 
397
405
  Returns:
398
406
  dict[str, MainSchemaTypes]: Dictionary of all schema organized by kind
399
407
  """
408
+ branch_schema = await self._fetch(branch=branch, namespaces=namespaces, timeout=timeout)
409
+ return branch_schema.nodes
410
+
411
+ async def _fetch(
412
+ self, branch: str, namespaces: list[str] | None = None, timeout: int | None = None
413
+ ) -> BranchSchema:
400
414
  url_parts = [("branch", branch)]
401
415
  if namespaces:
402
416
  url_parts.extend([("namespaces", ns) for ns in namespaces])
@@ -425,16 +439,22 @@ class InfrahubSchema(InfrahubSchemaBase):
425
439
  template = TemplateSchemaAPI(**template_schema)
426
440
  nodes[template.kind] = template
427
441
 
428
- return nodes
442
+ schema_hash = data.get("main", "")
443
+
444
+ return BranchSchema(hash=schema_hash, nodes=nodes)
429
445
 
430
446
 
431
447
  class InfrahubSchemaSync(InfrahubSchemaBase):
432
448
  def __init__(self, client: InfrahubClientSync):
433
449
  self.client = client
434
- self.cache: dict = defaultdict(lambda: dict)
450
+ self.cache: dict[str, BranchSchema] = {}
435
451
 
436
452
  def all(
437
- self, branch: str | None = None, refresh: bool = False, namespaces: list[str] | None = None
453
+ self,
454
+ branch: str | None = None,
455
+ refresh: bool = False,
456
+ namespaces: list[str] | None = None,
457
+ schema_hash: str | None = None,
438
458
  ) -> MutableMapping[str, MainSchemaTypesAPI]:
439
459
  """Retrieve the entire schema for a given branch.
440
460
 
@@ -444,15 +464,19 @@ class InfrahubSchemaSync(InfrahubSchemaBase):
444
464
  Args:
445
465
  branch (str, optional): Name of the branch to query. Defaults to default_branch.
446
466
  refresh (bool, optional): Force a refresh of the schema. Defaults to False.
467
+ schema_hash (str, optional): Only refresh if the current schema doesn't match this hash.
447
468
 
448
469
  Returns:
449
470
  dict[str, MainSchemaTypes]: Dictionary of all schema organized by kind
450
471
  """
451
472
  branch = branch or self.client.default_branch
473
+ if refresh and branch in self.cache and schema_hash and self.cache[branch].hash == schema_hash:
474
+ refresh = False
475
+
452
476
  if refresh or branch not in self.cache:
453
- self.cache[branch] = self.fetch(branch=branch, namespaces=namespaces)
477
+ self.cache[branch] = self._fetch(branch=branch, namespaces=namespaces)
454
478
 
455
- return self.cache[branch]
479
+ return self.cache[branch].nodes
456
480
 
457
481
  def get(
458
482
  self,
@@ -466,18 +490,18 @@ class InfrahubSchemaSync(InfrahubSchemaBase):
466
490
  kind_str = self._get_schema_name(schema=kind)
467
491
 
468
492
  if refresh:
469
- self.cache[branch] = self.fetch(branch=branch)
493
+ self.cache[branch] = self._fetch(branch=branch)
470
494
 
471
- if branch in self.cache and kind_str in self.cache[branch]:
472
- return self.cache[branch][kind_str]
495
+ if branch in self.cache and kind_str in self.cache[branch].nodes:
496
+ return self.cache[branch].nodes[kind_str]
473
497
 
474
498
  # Fetching the latest schema from the server if we didn't fetch it earlier
475
499
  # because we coulnd't find the object on the local cache
476
500
  if not refresh:
477
- self.cache[branch] = self.fetch(branch=branch, timeout=timeout)
501
+ self.cache[branch] = self._fetch(branch=branch, timeout=timeout)
478
502
 
479
- if branch in self.cache and kind_str in self.cache[branch]:
480
- return self.cache[branch][kind_str]
503
+ if branch in self.cache and kind_str in self.cache[branch].nodes:
504
+ return self.cache[branch].nodes[kind_str]
481
505
 
482
506
  raise SchemaNotFoundError(identifier=kind_str)
483
507
 
@@ -600,17 +624,20 @@ class InfrahubSchemaSync(InfrahubSchemaBase):
600
624
 
601
625
  Args:
602
626
  branch (str): Name of the branch to fetch the schema for.
603
- timeout (int, optional): Overrides default timeout used when querying the graphql API. Specified in seconds.
627
+ timeout (int, optional): Overrides default timeout used when querying the GraphQL API. Specified in seconds.
604
628
 
605
629
  Returns:
606
630
  dict[str, MainSchemaTypes]: Dictionary of all schema organized by kind
607
631
  """
632
+ branch_schema = self._fetch(branch=branch, namespaces=namespaces, timeout=timeout)
633
+ return branch_schema.nodes
634
+
635
+ def _fetch(self, branch: str, namespaces: list[str] | None = None, timeout: int | None = None) -> BranchSchema:
608
636
  url_parts = [("branch", branch)]
609
637
  if namespaces:
610
638
  url_parts.extend([("namespaces", ns) for ns in namespaces])
611
639
  query_params = urlencode(url_parts)
612
640
  url = f"{self.client.address}/api/schema?{query_params}"
613
-
614
641
  response = self.client._get(url=url, timeout=timeout)
615
642
  response.raise_for_status()
616
643
 
@@ -633,7 +660,9 @@ class InfrahubSchemaSync(InfrahubSchemaBase):
633
660
  template = TemplateSchemaAPI(**template_schema)
634
661
  nodes[template.kind] = template
635
662
 
636
- return nodes
663
+ schema_hash = data.get("main", "")
664
+
665
+ return BranchSchema(hash=schema_hash, nodes=nodes)
637
666
 
638
667
  def load(
639
668
  self, schemas: list[dict], branch: str | None = None, wait_until_converged: bool = False
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import warnings
4
+ from collections.abc import MutableMapping
4
5
  from enum import Enum
5
6
  from typing import TYPE_CHECKING, Any, Union
6
7
 
@@ -348,3 +349,10 @@ class SchemaRootAPI(BaseModel):
348
349
  nodes: list[NodeSchemaAPI] = Field(default_factory=list)
349
350
  profiles: list[ProfileSchemaAPI] = Field(default_factory=list)
350
351
  templates: list[TemplateSchemaAPI] = Field(default_factory=list)
352
+
353
+
354
+ class BranchSchema(BaseModel):
355
+ hash: str = Field(...)
356
+ nodes: MutableMapping[str, GenericSchemaAPI | NodeSchemaAPI | ProfileSchemaAPI | TemplateSchemaAPI] = Field(
357
+ default_factory=dict
358
+ )
@@ -0,0 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+ from .models import Task, TaskFilter, TaskLog, TaskRelatedNode, TaskState
4
+
5
+ __all__ = [
6
+ "Task",
7
+ "TaskFilter",
8
+ "TaskLog",
9
+ "TaskRelatedNode",
10
+ "TaskState",
11
+ ]
@@ -0,0 +1,3 @@
1
+ from .models import TaskState
2
+
3
+ FINAL_STATES = [TaskState.COMPLETED, TaskState.FAILED, TaskState.CANCELLED, TaskState.CRASHED]
@@ -0,0 +1,25 @@
1
+ from __future__ import annotations
2
+
3
+
4
+ class TaskError(Exception):
5
+ def __init__(self, message: str | None = None):
6
+ self.message = message
7
+ super().__init__(self.message)
8
+
9
+
10
+ class TaskNotFoundError(TaskError):
11
+ def __init__(self, id: str):
12
+ self.message = f"Task with id {id} not found"
13
+ super().__init__(self.message)
14
+
15
+
16
+ class TooManyTasksError(TaskError):
17
+ def __init__(self, expected_id: str, received_ids: list[str]):
18
+ self.message = f"Expected 1 task with id {expected_id}, but got {len(received_ids)}"
19
+ super().__init__(self.message)
20
+
21
+
22
+ class TaskNotCompletedError(TaskError):
23
+ def __init__(self, id: str, message: str | None = None):
24
+ self.message = message or f"Task with id {id} is not completed"
25
+ super().__init__(self.message)