infrahub-server 1.1.6__py3-none-any.whl → 1.2.0rc0__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 (346) 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} +2 -4
  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/tasks.py +63 -17
  16. infrahub/computed_attribute/triggers.py +90 -0
  17. infrahub/config.py +1 -1
  18. infrahub/context.py +39 -0
  19. infrahub/core/account.py +5 -8
  20. infrahub/core/attribute.py +53 -21
  21. infrahub/core/branch/models.py +4 -4
  22. infrahub/core/branch/tasks.py +89 -130
  23. infrahub/core/changelog/__init__.py +0 -0
  24. infrahub/core/changelog/diff.py +232 -0
  25. infrahub/core/changelog/models.py +488 -0
  26. infrahub/core/constants/__init__.py +19 -2
  27. infrahub/core/constants/infrahubkind.py +1 -0
  28. infrahub/core/diff/combiner.py +12 -8
  29. infrahub/core/diff/coordinator.py +49 -70
  30. infrahub/core/diff/data_check_synchronizer.py +86 -7
  31. infrahub/core/diff/enricher/aggregated.py +3 -3
  32. infrahub/core/diff/enricher/cardinality_one.py +2 -7
  33. infrahub/core/diff/enricher/hierarchy.py +5 -3
  34. infrahub/core/diff/enricher/labels.py +14 -4
  35. infrahub/core/diff/enricher/path_identifier.py +3 -9
  36. infrahub/core/diff/enricher/summary_counts.py +3 -1
  37. infrahub/core/diff/merger/merger.py +8 -4
  38. infrahub/core/diff/model/path.py +47 -29
  39. infrahub/core/diff/query/all_conflicts.py +6 -3
  40. infrahub/core/diff/query/artifact.py +1 -1
  41. infrahub/core/diff/query/delete_query.py +1 -1
  42. infrahub/core/diff/query/diff_get.py +3 -2
  43. infrahub/core/diff/query/diff_summary.py +1 -1
  44. infrahub/core/diff/query/field_specifiers.py +3 -1
  45. infrahub/core/diff/query/field_summary.py +3 -2
  46. infrahub/core/diff/query/filters.py +12 -1
  47. infrahub/core/diff/query/get_conflict_query.py +1 -1
  48. infrahub/core/diff/query/has_conflicts_query.py +6 -3
  49. infrahub/core/diff/query/merge.py +3 -3
  50. infrahub/core/diff/query/{drop_tracking_id.py → merge_tracking_id.py} +4 -4
  51. infrahub/core/diff/query/roots_metadata.py +9 -2
  52. infrahub/core/diff/query/save.py +151 -66
  53. infrahub/core/diff/query/summary_counts_enricher.py +220 -0
  54. infrahub/core/diff/query/time_range_query.py +3 -2
  55. infrahub/core/diff/query/update_conflict_query.py +1 -1
  56. infrahub/core/diff/query_parser.py +49 -24
  57. infrahub/core/diff/repository/deserializer.py +24 -25
  58. infrahub/core/diff/repository/repository.py +76 -20
  59. infrahub/core/diff/tasks.py +9 -8
  60. infrahub/core/enums.py +1 -1
  61. infrahub/core/integrity/object_conflict/conflict_recorder.py +1 -1
  62. infrahub/core/ipam/reconciler.py +1 -1
  63. infrahub/core/ipam/tasks.py +2 -3
  64. infrahub/core/manager.py +18 -13
  65. infrahub/core/merge.py +5 -2
  66. infrahub/core/migrations/graph/m001_add_version_to_graph.py +1 -1
  67. infrahub/core/migrations/graph/m002_attribute_is_default.py +2 -2
  68. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +2 -2
  69. infrahub/core/migrations/graph/m004_add_attr_documentation.py +1 -1
  70. infrahub/core/migrations/graph/m005_add_rel_read_only.py +1 -1
  71. infrahub/core/migrations/graph/m006_add_rel_on_delete.py +1 -1
  72. infrahub/core/migrations/graph/m007_add_rel_allow_override.py +1 -1
  73. infrahub/core/migrations/graph/m008_add_human_friendly_id.py +1 -1
  74. infrahub/core/migrations/graph/m009_add_generate_profile_attr.py +1 -1
  75. infrahub/core/migrations/graph/m010_add_generate_profile_attr_generic.py +1 -1
  76. infrahub/core/migrations/graph/m011_remove_profile_relationship_schema.py +2 -2
  77. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -23
  78. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -11
  79. infrahub/core/migrations/graph/m014_remove_index_attr_value.py +2 -2
  80. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
  81. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
  82. infrahub/core/migrations/graph/m017_add_core_profile.py +1 -1
  83. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -2
  84. infrahub/core/migrations/query/attribute_add.py +1 -1
  85. infrahub/core/migrations/query/attribute_rename.py +1 -1
  86. infrahub/core/migrations/query/delete_element_in_schema.py +1 -1
  87. infrahub/core/migrations/query/node_duplicate.py +1 -1
  88. infrahub/core/migrations/query/relationship_duplicate.py +1 -1
  89. infrahub/core/migrations/query/schema_attribute_update.py +1 -1
  90. infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
  91. infrahub/core/migrations/schema/node_remove.py +1 -1
  92. infrahub/core/migrations/schema/tasks.py +5 -5
  93. infrahub/core/migrations/shared.py +4 -4
  94. infrahub/core/models.py +7 -8
  95. infrahub/core/node/__init__.py +161 -40
  96. infrahub/core/node/base.py +1 -1
  97. infrahub/core/node/constraints/grouped_uniqueness.py +9 -2
  98. infrahub/core/node/delete_validator.py +4 -4
  99. infrahub/core/node/ipam.py +13 -8
  100. infrahub/core/node/permissions.py +4 -0
  101. infrahub/core/node/resource_manager/ip_prefix_pool.py +8 -5
  102. infrahub/core/node/standard.py +3 -5
  103. infrahub/core/property.py +1 -1
  104. infrahub/core/protocols.py +4 -0
  105. infrahub/core/protocols_base.py +4 -2
  106. infrahub/core/query/__init__.py +2 -5
  107. infrahub/core/query/attribute.py +9 -9
  108. infrahub/core/query/branch.py +5 -5
  109. infrahub/core/query/delete.py +1 -1
  110. infrahub/core/query/diff.py +45 -7
  111. infrahub/core/query/ipam.py +4 -4
  112. infrahub/core/query/node.py +19 -14
  113. infrahub/core/query/relationship.py +10 -11
  114. infrahub/core/query/resource_manager.py +13 -11
  115. infrahub/core/query/standard_node.py +6 -6
  116. infrahub/core/query/task.py +3 -3
  117. infrahub/core/query/task_log.py +1 -1
  118. infrahub/core/query/utils.py +5 -5
  119. infrahub/core/registry.py +0 -2
  120. infrahub/core/relationship/constraints/count.py +1 -1
  121. infrahub/core/relationship/constraints/peer_kind.py +1 -1
  122. infrahub/core/relationship/model.py +66 -26
  123. infrahub/core/schema/__init__.py +6 -4
  124. infrahub/core/schema/basenode_schema.py +1 -3
  125. infrahub/core/schema/definitions/core.py +14 -2
  126. infrahub/core/schema/definitions/internal.py +16 -0
  127. infrahub/core/schema/generated/genericnode_schema.py +5 -0
  128. infrahub/core/schema/generated/node_schema.py +5 -0
  129. infrahub/core/schema/generic_schema.py +5 -1
  130. infrahub/core/schema/manager.py +45 -42
  131. infrahub/core/schema/node_schema.py +4 -0
  132. infrahub/core/schema/profile_schema.py +4 -0
  133. infrahub/core/schema/relationship_schema.py +2 -2
  134. infrahub/core/schema/schema_branch.py +248 -14
  135. infrahub/core/schema/template_schema.py +36 -0
  136. infrahub/core/task/user_task.py +7 -5
  137. infrahub/core/timestamp.py +1 -1
  138. infrahub/core/utils.py +3 -2
  139. infrahub/core/validators/attribute/choices.py +1 -1
  140. infrahub/core/validators/attribute/enum.py +1 -1
  141. infrahub/core/validators/attribute/kind.py +1 -1
  142. infrahub/core/validators/attribute/length.py +1 -1
  143. infrahub/core/validators/attribute/optional.py +1 -1
  144. infrahub/core/validators/attribute/regex.py +1 -1
  145. infrahub/core/validators/attribute/unique.py +1 -1
  146. infrahub/core/validators/checks_runner.py +37 -0
  147. infrahub/core/validators/node/generate_profile.py +1 -1
  148. infrahub/core/validators/node/hierarchy.py +1 -1
  149. infrahub/core/validators/query.py +1 -1
  150. infrahub/core/validators/relationship/count.py +1 -1
  151. infrahub/core/validators/relationship/optional.py +1 -1
  152. infrahub/core/validators/relationship/peer.py +1 -1
  153. infrahub/core/validators/tasks.py +8 -6
  154. infrahub/core/validators/uniqueness/query.py +20 -17
  155. infrahub/database/__init__.py +15 -2
  156. infrahub/database/memgraph.py +1 -1
  157. infrahub/dependencies/builder/constraint/grouped/node_runner.py +0 -2
  158. infrahub/dependencies/builder/diff/combiner.py +1 -1
  159. infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
  160. infrahub/dependencies/builder/diff/coordinator.py +0 -2
  161. infrahub/dependencies/builder/diff/deserializer.py +1 -1
  162. infrahub/dependencies/builder/diff/enricher/summary_counts.py +1 -1
  163. infrahub/events/branch_action.py +47 -21
  164. infrahub/events/group_action.py +73 -0
  165. infrahub/events/models.py +159 -51
  166. infrahub/events/node_action.py +74 -8
  167. infrahub/events/repository_action.py +8 -8
  168. infrahub/events/schema_action.py +21 -8
  169. infrahub/generators/tasks.py +12 -13
  170. infrahub/git/base.py +3 -5
  171. infrahub/git/constants.py +0 -1
  172. infrahub/git/integrator.py +36 -35
  173. infrahub/git/repository.py +7 -8
  174. infrahub/git/tasks.py +43 -107
  175. infrahub/git_credential/helper.py +2 -3
  176. infrahub/graphql/analyzer.py +572 -11
  177. infrahub/graphql/app.py +34 -26
  178. infrahub/graphql/auth/query_permission_checker/anonymous_checker.py +5 -5
  179. infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +4 -4
  180. infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +4 -4
  181. infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +28 -35
  182. infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -5
  183. infrahub/graphql/enums.py +1 -1
  184. infrahub/graphql/initialization.py +5 -1
  185. infrahub/graphql/loaders/node.py +2 -2
  186. infrahub/graphql/manager.py +59 -54
  187. infrahub/graphql/mutations/account.py +20 -13
  188. infrahub/graphql/mutations/artifact_definition.py +16 -12
  189. infrahub/graphql/mutations/branch.py +61 -40
  190. infrahub/graphql/mutations/computed_attribute.py +19 -13
  191. infrahub/graphql/mutations/diff.py +37 -9
  192. infrahub/graphql/mutations/diff_conflict.py +9 -8
  193. infrahub/graphql/mutations/graphql_query.py +19 -11
  194. infrahub/graphql/mutations/ipam.py +21 -19
  195. infrahub/graphql/mutations/main.py +197 -44
  196. infrahub/graphql/mutations/menu.py +8 -8
  197. infrahub/graphql/mutations/proposed_change.py +36 -28
  198. infrahub/graphql/mutations/relationship.py +302 -105
  199. infrahub/graphql/mutations/repository.py +41 -35
  200. infrahub/graphql/mutations/resource_manager.py +26 -26
  201. infrahub/graphql/mutations/schema.py +51 -33
  202. infrahub/graphql/mutations/tasks.py +16 -10
  203. infrahub/graphql/parser.py +1 -1
  204. infrahub/graphql/permissions.py +6 -4
  205. infrahub/graphql/queries/account.py +22 -18
  206. infrahub/graphql/queries/branch.py +6 -4
  207. infrahub/graphql/queries/diff/tree.py +48 -42
  208. infrahub/graphql/queries/event.py +112 -0
  209. infrahub/graphql/queries/internal.py +3 -3
  210. infrahub/graphql/queries/ipam.py +23 -18
  211. infrahub/graphql/queries/relationship.py +11 -10
  212. infrahub/graphql/queries/resource_manager.py +43 -27
  213. infrahub/graphql/queries/search.py +9 -8
  214. infrahub/graphql/queries/status.py +12 -9
  215. infrahub/graphql/queries/task.py +11 -9
  216. infrahub/graphql/resolvers/resolver.py +69 -43
  217. infrahub/graphql/resolvers/single_relationship.py +16 -10
  218. infrahub/graphql/schema.py +2 -0
  219. infrahub/graphql/subscription/__init__.py +1 -1
  220. infrahub/graphql/subscription/events.py +1 -1
  221. infrahub/graphql/subscription/graphql_query.py +8 -8
  222. infrahub/graphql/types/branch.py +2 -2
  223. infrahub/graphql/types/common.py +6 -1
  224. infrahub/graphql/types/enums.py +2 -0
  225. infrahub/graphql/types/event.py +100 -0
  226. infrahub/graphql/types/interface.py +2 -2
  227. infrahub/graphql/types/node.py +3 -3
  228. infrahub/graphql/types/permission.py +2 -2
  229. infrahub/graphql/types/relationship.py +3 -3
  230. infrahub/graphql/types/standard_node.py +9 -11
  231. infrahub/graphql/utils.py +28 -182
  232. infrahub/groups/tasks.py +2 -3
  233. infrahub/lock.py +1 -1
  234. infrahub/menu/constants.py +1 -0
  235. infrahub/menu/generator.py +14 -3
  236. infrahub/menu/menu.py +116 -127
  237. infrahub/menu/models.py +4 -4
  238. infrahub/message_bus/messages/__init__.py +0 -4
  239. infrahub/message_bus/messages/event_branch_merge.py +3 -0
  240. infrahub/message_bus/messages/request_proposedchange_pipeline.py +2 -0
  241. infrahub/message_bus/operations/__init__.py +3 -5
  242. infrahub/message_bus/operations/check/__init__.py +2 -2
  243. infrahub/message_bus/operations/check/generator.py +1 -3
  244. infrahub/message_bus/operations/check/repository.py +1 -1
  245. infrahub/message_bus/operations/event/branch.py +7 -3
  246. infrahub/message_bus/operations/event/schema.py +1 -1
  247. infrahub/message_bus/operations/finalize/validator.py +1 -1
  248. infrahub/message_bus/operations/git/file.py +2 -2
  249. infrahub/message_bus/operations/git/repository.py +1 -1
  250. infrahub/message_bus/operations/requests/__init__.py +0 -2
  251. infrahub/message_bus/operations/requests/generator_definition.py +1 -1
  252. infrahub/message_bus/operations/requests/proposed_change.py +26 -11
  253. infrahub/message_bus/operations/requests/repository.py +2 -2
  254. infrahub/message_bus/operations/send/echo.py +1 -1
  255. infrahub/message_bus/types.py +1 -1
  256. infrahub/permissions/__init__.py +2 -1
  257. infrahub/permissions/types.py +26 -0
  258. infrahub/pools/prefix.py +29 -165
  259. infrahub/prefect_server/__init__.py +0 -0
  260. infrahub/prefect_server/app.py +18 -0
  261. infrahub/prefect_server/database.py +20 -0
  262. infrahub/prefect_server/events.py +28 -0
  263. infrahub/prefect_server/models.py +46 -0
  264. infrahub/proposed_change/models.py +15 -1
  265. infrahub/proposed_change/tasks.py +173 -35
  266. infrahub/pytest_plugin.py +4 -4
  267. infrahub/server.py +12 -11
  268. infrahub/services/__init__.py +147 -62
  269. infrahub/services/adapters/cache/__init__.py +7 -5
  270. infrahub/services/adapters/cache/nats.py +40 -22
  271. infrahub/services/adapters/cache/redis.py +0 -4
  272. infrahub/services/adapters/event/__init__.py +10 -18
  273. infrahub/services/adapters/http/__init__.py +0 -5
  274. infrahub/services/adapters/http/httpx.py +22 -15
  275. infrahub/services/adapters/message_bus/__init__.py +23 -6
  276. infrahub/services/adapters/message_bus/local.py +8 -6
  277. infrahub/services/adapters/message_bus/nats.py +12 -6
  278. infrahub/services/adapters/message_bus/rabbitmq.py +22 -9
  279. infrahub/services/adapters/workflow/__init__.py +11 -8
  280. infrahub/services/adapters/workflow/local.py +28 -7
  281. infrahub/services/adapters/workflow/worker.py +23 -7
  282. infrahub/services/component.py +38 -35
  283. infrahub/services/scheduler.py +32 -29
  284. infrahub/storage.py +2 -4
  285. infrahub/task_manager/constants.py +1 -1
  286. infrahub/task_manager/event.py +182 -0
  287. infrahub/task_manager/models.py +125 -1
  288. infrahub/task_manager/task.py +1 -1
  289. infrahub/tasks/artifact.py +14 -16
  290. infrahub/tasks/registry.py +1 -1
  291. infrahub/tasks/telemetry.py +13 -14
  292. infrahub/transformations/tasks.py +3 -5
  293. infrahub/trigger/__init__.py +0 -0
  294. infrahub/trigger/catalogue.py +15 -0
  295. infrahub/trigger/constants.py +9 -0
  296. infrahub/trigger/models.py +69 -0
  297. infrahub/trigger/tasks.py +85 -0
  298. infrahub/types.py +1 -1
  299. infrahub/utils.py +1 -1
  300. infrahub/webhook/constants.py +0 -2
  301. infrahub/webhook/models.py +8 -2
  302. infrahub/webhook/tasks.py +20 -73
  303. infrahub/webhook/triggers.py +20 -0
  304. infrahub/workers/infrahub_async.py +36 -25
  305. infrahub/workers/utils.py +63 -0
  306. infrahub/workflows/catalogue.py +13 -37
  307. infrahub/workflows/initialization.py +6 -8
  308. infrahub/workflows/models.py +3 -5
  309. infrahub/workflows/utils.py +1 -1
  310. infrahub_sdk/ctl/check.py +3 -3
  311. infrahub_sdk/ctl/cli_commands.py +11 -10
  312. infrahub_sdk/ctl/exceptions.py +0 -6
  313. infrahub_sdk/ctl/exporter.py +1 -1
  314. infrahub_sdk/ctl/generator.py +5 -5
  315. infrahub_sdk/ctl/importer.py +3 -2
  316. infrahub_sdk/ctl/menu.py +1 -1
  317. infrahub_sdk/ctl/object.py +1 -1
  318. infrahub_sdk/ctl/repository.py +23 -15
  319. infrahub_sdk/ctl/schema.py +2 -2
  320. infrahub_sdk/ctl/utils.py +4 -3
  321. infrahub_sdk/ctl/validate.py +2 -1
  322. infrahub_sdk/exceptions.py +6 -0
  323. infrahub_sdk/generator.py +3 -0
  324. infrahub_sdk/node.py +2 -2
  325. infrahub_sdk/schema/__init__.py +14 -2
  326. infrahub_sdk/schema/main.py +7 -0
  327. infrahub_sdk/utils.py +11 -1
  328. infrahub_sdk/yaml.py +2 -3
  329. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/METADATA +46 -12
  330. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/RECORD +338 -321
  331. infrahub_testcontainers/container.py +14 -6
  332. infrahub_testcontainers/docker-compose.test.yml +24 -5
  333. infrahub_testcontainers/haproxy.cfg +43 -0
  334. infrahub_testcontainers/helpers.py +85 -1
  335. infrahub/core/branch/constants.py +0 -2
  336. infrahub/graphql/query.py +0 -52
  337. infrahub/message_bus/messages/request_artifactdefinition_check.py +0 -17
  338. infrahub/message_bus/operations/requests/artifact_definition.py +0 -148
  339. infrahub/schema/constants.py +0 -1
  340. infrahub/schema/tasks.py +0 -76
  341. infrahub/services/adapters/database/__init__.py +0 -9
  342. infrahub_sdk/ctl/_file.py +0 -13
  343. /infrahub/{schema → artifacts}/__init__.py +0 -0
  344. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/LICENSE.txt +0 -0
  345. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/WHEEL +0 -0
  346. {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0rc0.dist-info}/entry_points.txt +0 -0
@@ -22,13 +22,11 @@ if TYPE_CHECKING:
22
22
  from infrahub.core.schema import GenericSchema, NodeSchema
23
23
  from infrahub.core.schema.schema_branch import SchemaBranch
24
24
 
25
- # pylint: disable=redefined-builtin
26
-
27
25
 
28
26
  NODE_METADATA_ATTRIBUTES = ["_source", "_owner"]
29
27
 
30
28
 
31
- class BaseNodeSchema(GeneratedBaseNodeSchema): # pylint: disable=too-many-public-methods
29
+ class BaseNodeSchema(GeneratedBaseNodeSchema):
32
30
  _exclude_from_hash: list[str] = ["attributes", "relationships"]
33
31
  _sort_by: list[str] = ["namespace", "name"]
34
32
 
@@ -26,8 +26,6 @@ from infrahub.core.constants import (
26
26
  )
27
27
  from infrahub.proposed_change.constants import ProposedChangeState
28
28
 
29
- # pylint: disable=too-many-lines
30
-
31
29
  core_profile_schema_definition: dict[str, Any] = {
32
30
  "name": "Profile",
33
31
  "namespace": "Core",
@@ -969,6 +967,20 @@ core_models: dict[str, Any] = {
969
967
  {"name": "description", "kind": "Text", "optional": True, "order_weight": 3000},
970
968
  ],
971
969
  },
970
+ {
971
+ "name": "ObjectTemplate",
972
+ "namespace": "Core",
973
+ "include_in_menu": False,
974
+ "icon": "mdi:pencil-ruler",
975
+ "description": "Template to create pre-shaped objects.",
976
+ "label": "Object Templates",
977
+ "display_labels": ["template_name__value"],
978
+ "default_filter": "template_name__value",
979
+ "uniqueness_constraints": [["template_name__value"]],
980
+ "attributes": [
981
+ {"name": "template_name", "kind": "Text", "optional": False, "unique": True, "order_weight": 1000}
982
+ ],
983
+ },
972
984
  generic_menu_item,
973
985
  ],
974
986
  "nodes": [
@@ -394,6 +394,14 @@ node_schema = SchemaNode(
394
394
  optional=True,
395
395
  extra={"update": UpdateSupport.VALIDATE_CONSTRAINT},
396
396
  ),
397
+ SchemaAttribute(
398
+ name="generate_template",
399
+ kind="Boolean",
400
+ description="Indicate if an object template schema should be generated for this schema",
401
+ default_value=False,
402
+ optional=True,
403
+ extra={"update": UpdateSupport.ALLOWED},
404
+ ),
397
405
  SchemaAttribute(
398
406
  name="hierarchy",
399
407
  kind="Text",
@@ -858,6 +866,14 @@ generic_schema = SchemaNode(
858
866
  optional=True,
859
867
  extra={"update": UpdateSupport.VALIDATE_CONSTRAINT},
860
868
  ),
869
+ SchemaAttribute(
870
+ name="generate_template",
871
+ kind="Boolean",
872
+ description="Indicate if an object template schema should be generated for this schema",
873
+ default_value=False,
874
+ optional=True,
875
+ extra={"update": UpdateSupport.ALLOWED},
876
+ ),
861
877
  SchemaAttribute(
862
878
  name="used_by",
863
879
  kind="List",
@@ -18,6 +18,11 @@ class GeneratedGenericSchema(BaseNodeSchema):
18
18
  description="Indicate if a profile schema should be generated for this schema",
19
19
  json_schema_extra={"update": "validate_constraint"},
20
20
  )
21
+ generate_template: bool = Field(
22
+ default=False,
23
+ description="Indicate if an object template schema should be generated for this schema",
24
+ json_schema_extra={"update": "allowed"},
25
+ )
21
26
  used_by: list[str] = Field(
22
27
  default_factory=list,
23
28
  description="List of Nodes that are referencing this Generic",
@@ -20,6 +20,11 @@ class GeneratedNodeSchema(BaseNodeSchema):
20
20
  description="Indicate if a profile schema should be generated for this schema",
21
21
  json_schema_extra={"update": "validate_constraint"},
22
22
  )
23
+ generate_template: bool = Field(
24
+ default=False,
25
+ description="Indicate if an object template schema should be generated for this schema",
26
+ json_schema_extra={"update": "allowed"},
27
+ )
23
28
  hierarchy: Optional[str] = Field(
24
29
  default=None,
25
30
  description="Internal value to track the name of the Hierarchy, must match the name of a Generic supporting hierarchical mode",
@@ -24,7 +24,11 @@ class GenericSchema(GeneratedGenericSchema):
24
24
  def is_profile_schema(self) -> bool:
25
25
  return False
26
26
 
27
- def get_hierarchy_schema(self, db: InfrahubDatabase, branch: Optional[Union[Branch, str]] = None) -> GenericSchema: # pylint: disable=unused-argument
27
+ @property
28
+ def is_template_schema(self) -> bool:
29
+ return False
30
+
31
+ def get_hierarchy_schema(self, db: InfrahubDatabase, branch: Optional[Union[Branch, str]] = None) -> GenericSchema: # noqa: ARG002
28
32
  if self.hierarchical:
29
33
  return self
30
34
 
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Any, Optional, Union
3
+ from typing import TYPE_CHECKING, Any
4
4
 
5
5
  from infrahub import lock
6
6
  from infrahub.core.manager import NodeManager
@@ -19,6 +19,7 @@ from infrahub.core.schema import (
19
19
  ProfileSchema,
20
20
  RelationshipSchema,
21
21
  SchemaRoot,
22
+ TemplateSchema,
22
23
  )
23
24
  from infrahub.core.utils import parse_node_kind
24
25
  from infrahub.exceptions import SchemaNotFoundError
@@ -35,7 +36,6 @@ if TYPE_CHECKING:
35
36
  from infrahub.database import InfrahubDatabase
36
37
 
37
38
 
38
- # pylint: disable=too-many-public-methods
39
39
  class SchemaManager(NodeManager):
40
40
  def __init__(self) -> None:
41
41
  self._cache: dict[int, Any] = {}
@@ -44,7 +44,7 @@ class SchemaManager(NodeManager):
44
44
  def _get_from_cache(self, key: int) -> Any:
45
45
  return self._cache[key]
46
46
 
47
- def set(self, name: str, schema: Union[NodeSchema, GenericSchema], branch: Optional[str] = None) -> int:
47
+ def set(self, name: str, schema: NodeSchema | GenericSchema, branch: str | None = None) -> int:
48
48
  branch = branch or registry.default_branch
49
49
 
50
50
  if branch not in self._branches:
@@ -54,7 +54,7 @@ class SchemaManager(NodeManager):
54
54
 
55
55
  return hash(self._branches[branch])
56
56
 
57
- def has(self, name: str, branch: Optional[Union[Branch, str]] = None) -> bool:
57
+ def has(self, name: str, branch: Branch | str | None = None) -> bool:
58
58
  try:
59
59
  self.get(name=name, branch=branch, duplicate=False)
60
60
  return True
@@ -64,7 +64,7 @@ class SchemaManager(NodeManager):
64
64
  def get(
65
65
  self,
66
66
  name: str,
67
- branch: Optional[Union[Branch, str]] = None,
67
+ branch: Branch | str | None = None,
68
68
  duplicate: bool = True,
69
69
  check_branch_only: bool = False,
70
70
  ) -> MainSchemaTypes:
@@ -86,9 +86,7 @@ class SchemaManager(NodeManager):
86
86
  default_branch = registry.default_branch
87
87
  return self._branches[default_branch].get(name=name, duplicate=duplicate)
88
88
 
89
- def get_node_schema(
90
- self, name: str, branch: Optional[Union[Branch, str]] = None, duplicate: bool = True
91
- ) -> NodeSchema:
89
+ def get_node_schema(self, name: str, branch: Branch | str | None = None, duplicate: bool = True) -> NodeSchema:
92
90
  schema = self.get(name=name, branch=branch, duplicate=duplicate)
93
91
  if isinstance(schema, NodeSchema):
94
92
  return schema
@@ -96,7 +94,7 @@ class SchemaManager(NodeManager):
96
94
  raise ValueError("The selected node is not of type NodeSchema")
97
95
 
98
96
  def get_profile_schema(
99
- self, name: str, branch: Optional[Union[Branch, str]] = None, duplicate: bool = True
97
+ self, name: str, branch: Branch | str | None = None, duplicate: bool = True
100
98
  ) -> ProfileSchema:
101
99
  schema = self.get(name=name, branch=branch, duplicate=duplicate)
102
100
  if isinstance(schema, ProfileSchema):
@@ -104,9 +102,16 @@ class SchemaManager(NodeManager):
104
102
 
105
103
  raise ValueError("The selected node is not of type ProfileSchema")
106
104
 
107
- def get_full(
108
- self, branch: Optional[Union[Branch, str]] = None, duplicate: bool = True
109
- ) -> dict[str, MainSchemaTypes]:
105
+ def get_template_schema(
106
+ self, name: str, branch: Branch | str | None = None, duplicate: bool = True
107
+ ) -> TemplateSchema:
108
+ schema = self.get(name=name, branch=branch, duplicate=duplicate)
109
+ if isinstance(schema, TemplateSchema):
110
+ return schema
111
+
112
+ raise ValueError("The selected node is not of type TemplateSchema")
113
+
114
+ def get_full(self, branch: Branch | str | None = None, duplicate: bool = True) -> dict[str, MainSchemaTypes]:
110
115
  branch = registry.get_branch_from_registry(branch=branch)
111
116
 
112
117
  branch_name = None
@@ -117,9 +122,7 @@ class SchemaManager(NodeManager):
117
122
 
118
123
  return self._branches[branch_name].get_all(duplicate=duplicate)
119
124
 
120
- async def get_full_safe(
121
- self, branch: Optional[Union[Branch, str]] = None
122
- ) -> dict[str, Union[NodeSchema, GenericSchema]]:
125
+ async def get_full_safe(self, branch: Branch | str | None = None) -> dict[str, NodeSchema | GenericSchema]:
123
126
  await lock.registry.local_schema_wait()
124
127
 
125
128
  return self.get_full(branch=branch)
@@ -143,9 +146,9 @@ class SchemaManager(NodeManager):
143
146
  self,
144
147
  schema: SchemaBranch,
145
148
  db: InfrahubDatabase,
146
- branch: Optional[Union[Branch, str]] = None,
147
- diff: Optional[SchemaDiff] = None,
148
- limit: Optional[list[str]] = None,
149
+ branch: Branch | str | None = None,
150
+ diff: SchemaDiff | None = None,
151
+ limit: list[str] | None = None,
149
152
  update_db: bool = True,
150
153
  ) -> None:
151
154
  branch = await registry.get_branch(branch=branch, db=db)
@@ -172,7 +175,7 @@ class SchemaManager(NodeManager):
172
175
 
173
176
  self.set_schema_branch(name=branch.name, schema=updated_schema or schema)
174
177
 
175
- def register_schema(self, schema: SchemaRoot, branch: Optional[str] = None) -> SchemaBranch:
178
+ def register_schema(self, schema: SchemaRoot, branch: str | None = None) -> SchemaBranch:
176
179
  """Register all nodes, generics & groups from a SchemaRoot object into the registry."""
177
180
 
178
181
  branch = branch or registry.default_branch
@@ -186,7 +189,7 @@ class SchemaManager(NodeManager):
186
189
  schema: SchemaBranch,
187
190
  db: InfrahubDatabase,
188
191
  diff: SchemaDiff,
189
- branch: Optional[Union[str, Branch]] = None,
192
+ branch: Branch | str | None = None,
190
193
  ) -> SchemaBranchDiff:
191
194
  """Load all nodes, generics and groups from a SchemaRoot object into the database."""
192
195
 
@@ -194,7 +197,7 @@ class SchemaManager(NodeManager):
194
197
 
195
198
  added_nodes = []
196
199
  added_generics = []
197
- for item_kind, item_diff in diff.added.items():
200
+ for item_kind in diff.added.keys():
198
201
  item = schema.get(name=item_kind, duplicate=False)
199
202
  node = await self.load_node_to_db(node=item, branch=branch, db=db)
200
203
  schema.set(name=item_kind, schema=node)
@@ -219,7 +222,7 @@ class SchemaManager(NodeManager):
219
222
 
220
223
  removed_nodes = []
221
224
  removed_generics = []
222
- for item_kind, item_diff in diff.removed.items():
225
+ for item_kind in diff.removed.keys():
223
226
  item = schema.get(name=item_kind, duplicate=False)
224
227
  node = await self.delete_node_in_db(node=item, branch=branch, db=db)
225
228
  schema.delete(name=item_kind)
@@ -241,8 +244,8 @@ class SchemaManager(NodeManager):
241
244
  self,
242
245
  schema: SchemaBranch,
243
246
  db: InfrahubDatabase,
244
- branch: Optional[Union[str, Branch]] = None,
245
- limit: Optional[list[str]] = None,
247
+ branch: Branch | str | None = None,
248
+ limit: list[str] | None = None,
246
249
  ) -> None:
247
250
  """Load all nodes, generics and groups from a SchemaRoot object into the database."""
248
251
 
@@ -261,10 +264,10 @@ class SchemaManager(NodeManager):
261
264
 
262
265
  async def load_node_to_db(
263
266
  self,
264
- node: Union[NodeSchema, GenericSchema],
267
+ node: NodeSchema | GenericSchema,
265
268
  db: InfrahubDatabase,
266
- branch: Optional[Union[str, Branch]] = None,
267
- ) -> Union[NodeSchema, GenericSchema]:
269
+ branch: Branch | str | None = None,
270
+ ) -> NodeSchema | GenericSchema:
268
271
  """Load a Node with its attributes and its relationships to the database."""
269
272
  branch = await registry.get_branch(branch=branch, db=db)
270
273
 
@@ -287,7 +290,7 @@ class SchemaManager(NodeManager):
287
290
  new_node.id = obj.id
288
291
 
289
292
  # Then create the Attributes and the relationships
290
- if isinstance(node, (NodeSchema, GenericSchema)):
293
+ if isinstance(node, NodeSchema | GenericSchema):
291
294
  new_node.relationships = []
292
295
  new_node.attributes = []
293
296
 
@@ -310,9 +313,9 @@ class SchemaManager(NodeManager):
310
313
  async def update_node_in_db(
311
314
  self,
312
315
  db: InfrahubDatabase,
313
- node: Union[NodeSchema, GenericSchema],
314
- branch: Optional[Union[str, Branch]] = None,
315
- ) -> Union[NodeSchema, GenericSchema]:
316
+ node: NodeSchema | GenericSchema,
317
+ branch: Branch | str | None = None,
318
+ ) -> NodeSchema | GenericSchema:
316
319
  """Update a Node with its attributes and its relationships in the database."""
317
320
  branch = await registry.get_branch(branch=branch, db=db)
318
321
 
@@ -372,13 +375,13 @@ class SchemaManager(NodeManager):
372
375
  self.set(name=new_node.kind, schema=new_node, branch=branch.name)
373
376
  return new_node
374
377
 
375
- async def update_node_in_db_based_on_diff( # pylint: disable=too-many-branches,too-many-statements
378
+ async def update_node_in_db_based_on_diff(
376
379
  self,
377
380
  db: InfrahubDatabase,
378
381
  diff: HashableModelDiff,
379
- node: Union[NodeSchema, GenericSchema],
380
- branch: Optional[Union[str, Branch]] = None,
381
- ) -> Union[NodeSchema, GenericSchema]:
382
+ node: NodeSchema | GenericSchema,
383
+ branch: Branch | str | None = None,
384
+ ) -> NodeSchema | GenericSchema:
382
385
  """Update a Node with its attributes and its relationships in the database based on a HashableModelDiff."""
383
386
  branch = await registry.get_branch(branch=branch, db=db)
384
387
 
@@ -517,8 +520,8 @@ class SchemaManager(NodeManager):
517
520
  async def delete_node_in_db(
518
521
  self,
519
522
  db: InfrahubDatabase,
520
- node: Union[NodeSchema, GenericSchema],
521
- branch: Optional[Union[str, Branch]] = None,
523
+ node: NodeSchema | GenericSchema,
524
+ branch: Branch | str | None = None,
522
525
  ) -> None:
523
526
  """Delete the node with its attributes and relationships."""
524
527
  branch = await registry.get_branch(branch=branch, db=db)
@@ -584,7 +587,7 @@ class SchemaManager(NodeManager):
584
587
  async def load_schema(
585
588
  self,
586
589
  db: InfrahubDatabase,
587
- branch: Optional[Union[str, Branch]] = None,
590
+ branch: Branch | str | None = None,
588
591
  ) -> SchemaBranch:
589
592
  """Load the schema either from the cache or from the database"""
590
593
  branch = await registry.get_branch(branch=branch, db=db)
@@ -610,10 +613,10 @@ class SchemaManager(NodeManager):
610
613
  async def load_schema_from_db(
611
614
  self,
612
615
  db: InfrahubDatabase,
613
- branch: Optional[Union[str, Branch]] = None,
614
- schema: Optional[SchemaBranch] = None,
615
- schema_diff: Optional[SchemaBranchDiff] = None,
616
- at: Optional[Timestamp] = None,
616
+ branch: Branch | str | None = None,
617
+ schema: SchemaBranch | None = None,
618
+ schema_diff: SchemaBranchDiff | None = None,
619
+ at: Timestamp | None = None,
617
620
  validate_schema: bool = True,
618
621
  ) -> SchemaBranch:
619
622
  """Query all the node of type NodeSchema and GenericSchema from the database and convert them to their respective type.
@@ -25,6 +25,10 @@ class NodeSchema(GeneratedNodeSchema):
25
25
  def is_profile_schema(self) -> bool:
26
26
  return False
27
27
 
28
+ @property
29
+ def is_template_schema(self) -> bool:
30
+ return False
31
+
28
32
  def validate_inheritance(self, interface: GenericSchema) -> None:
29
33
  """Perform checks specific to inheritance from Generics.
30
34
 
@@ -24,6 +24,10 @@ class ProfileSchema(BaseNodeSchema):
24
24
  def is_profile_schema(self) -> bool:
25
25
  return True
26
26
 
27
+ @property
28
+ def is_template_schema(self) -> bool:
29
+ return False
30
+
27
31
  def get_labels(self) -> list[str]:
28
32
  """Return the labels for this object, composed of the kind
29
33
  and the list of Generic this object is inheriting from."""
@@ -72,12 +72,12 @@ class RelationshipSchema(GeneratedRelationshipSchema):
72
72
  db: InfrahubDatabase,
73
73
  filter_name: str,
74
74
  filter_value: Optional[Union[str, int, bool]] = None,
75
- name: Optional[str] = None, # pylint: disable=unused-argument
75
+ name: Optional[str] = None, # noqa: ARG002
76
76
  branch: Optional[Branch] = None,
77
77
  include_match: bool = True,
78
78
  param_prefix: Optional[str] = None,
79
79
  partial_match: bool = False,
80
- support_profiles: bool = False, # pylint: disable=unused-argument
80
+ support_profiles: bool = False, # noqa: ARG002
81
81
  ) -> tuple[list[QueryElement], dict[str, Any], list[str]]:
82
82
  """Generate Query String Snippet to filter the right node."""
83
83