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
@@ -0,0 +1,134 @@
1
+ from infrahub.core.constants import (
2
+ AllowOverrideType,
3
+ BranchSupportType,
4
+ EventType,
5
+ InfrahubKind,
6
+ )
7
+ from infrahub.core.constants import RelationshipCardinality as Cardinality
8
+ from infrahub.core.constants import RelationshipKind as RelKind
9
+
10
+ from ...attribute_schema import AttributeSchema as Attr
11
+ from ...dropdown import DropdownChoice
12
+ from ...generic_schema import GenericSchema
13
+ from ...node_schema import NodeSchema
14
+ from ...relationship_schema import (
15
+ RelationshipSchema as Rel,
16
+ )
17
+
18
+ core_webhook = GenericSchema(
19
+ name="Webhook",
20
+ namespace="Core",
21
+ description="A webhook that connects to an external integration",
22
+ label="Webhook",
23
+ default_filter="name__value",
24
+ order_by=["name__value"],
25
+ display_labels=["name__value"],
26
+ include_in_menu=False,
27
+ icon="mdi:webhook",
28
+ branch=BranchSupportType.AGNOSTIC,
29
+ uniqueness_constraints=[["name__value"]],
30
+ attributes=[
31
+ Attr(name="name", kind="Text", unique=True, order_weight=1000),
32
+ Attr(
33
+ name="event_type",
34
+ kind="Text",
35
+ enum=["all"] + EventType.available_types(),
36
+ default_value="all",
37
+ order_weight=1500,
38
+ description="The event type that triggers the webhook",
39
+ ),
40
+ Attr(
41
+ name="branch_scope",
42
+ kind="Dropdown",
43
+ choices=[
44
+ DropdownChoice(
45
+ name="all_branches",
46
+ label="All Branches",
47
+ description="All branches",
48
+ color="#fef08a",
49
+ ),
50
+ DropdownChoice(
51
+ name="default_branch",
52
+ label="Default Branch",
53
+ description="Only the default branch",
54
+ color="#86efac",
55
+ ),
56
+ DropdownChoice(
57
+ name="other_branches",
58
+ label="Other Branches",
59
+ description="All branches except the default branch",
60
+ color="#e5e7eb",
61
+ ),
62
+ ],
63
+ default_value="default_branch",
64
+ optional=False,
65
+ order_weight=2000,
66
+ allow_override=AllowOverrideType.NONE,
67
+ ),
68
+ Attr(
69
+ name="node_kind",
70
+ kind="Text",
71
+ optional=True,
72
+ description="Only send node mutation events for nodes of this kind",
73
+ order_weight=2250,
74
+ ),
75
+ Attr(
76
+ name="description",
77
+ kind="Text",
78
+ optional=True,
79
+ order_weight=2500,
80
+ ),
81
+ Attr(name="url", kind="URL", order_weight=3000),
82
+ Attr(
83
+ name="validate_certificates",
84
+ kind="Boolean",
85
+ default_value=True,
86
+ optional=True,
87
+ order_weight=5000,
88
+ ),
89
+ ],
90
+ )
91
+
92
+ core_standard_webhook = NodeSchema(
93
+ name="StandardWebhook",
94
+ namespace="Core",
95
+ description="A webhook that connects to an external integration",
96
+ label="Standard Webhook",
97
+ default_filter="name__value",
98
+ order_by=["name__value"],
99
+ display_labels=["name__value"],
100
+ include_in_menu=False,
101
+ icon="mdi:webhook",
102
+ branch=BranchSupportType.AGNOSTIC,
103
+ generate_profile=False,
104
+ inherit_from=[InfrahubKind.WEBHOOK, InfrahubKind.TASKTARGET],
105
+ attributes=[
106
+ Attr(name="shared_key", kind="Password", unique=False, order_weight=4000),
107
+ ],
108
+ )
109
+
110
+ core_custom_webhook = NodeSchema(
111
+ name="CustomWebhook",
112
+ namespace="Core",
113
+ description="A webhook that connects to an external integration",
114
+ label="Custom Webhook",
115
+ default_filter="name__value",
116
+ order_by=["name__value"],
117
+ display_labels=["name__value"],
118
+ include_in_menu=False,
119
+ icon="mdi:cog-outline",
120
+ branch=BranchSupportType.AGNOSTIC,
121
+ generate_profile=False,
122
+ inherit_from=[InfrahubKind.WEBHOOK, InfrahubKind.TASKTARGET],
123
+ relationships=[
124
+ Rel(
125
+ name="transformation",
126
+ peer=InfrahubKind.TRANSFORMPYTHON,
127
+ kind=RelKind.ATTRIBUTE,
128
+ identifier="webhook___transformation",
129
+ cardinality=Cardinality.ONE,
130
+ optional=True,
131
+ order_weight=7000,
132
+ ),
133
+ ],
134
+ )
@@ -4,7 +4,7 @@ from copy import deepcopy
4
4
  from dataclasses import dataclass
5
5
  from enum import Enum
6
6
  from types import GenericAlias
7
- from typing import Any, Optional, Union
7
+ from typing import Any
8
8
 
9
9
  from pydantic import BaseModel, ConfigDict, Field
10
10
  from typing_extensions import TypedDict
@@ -46,17 +46,17 @@ class SchemaAttribute(BaseModel):
46
46
  kind: str
47
47
  description: str
48
48
  extra: ExtraField
49
- internal_kind: Optional[Union[type[Any], GenericAlias]] = None
50
- regex: Optional[str] = None
51
- unique: Optional[bool] = None
52
- optional: Optional[bool] = None
53
- min_length: Optional[int] = None
54
- max_length: Optional[int] = None
55
- enum: Optional[list[str]] = None
56
- default_value: Optional[Any] = None
57
- default_factory: Optional[str] = None
49
+ internal_kind: type[Any] | GenericAlias | None = None
50
+ regex: str | None = None
51
+ unique: bool | None = None
52
+ optional: bool | None = None
53
+ min_length: int | None = None
54
+ max_length: int | None = None
55
+ enum: list[str] | None = None
56
+ default_value: Any | None = None
57
+ default_factory: str | None = None
58
58
  default_to_none: bool = False
59
- override_default_value: Optional[Any] = Field(
59
+ override_default_value: Any | None = Field(
60
60
  default=None,
61
61
  description="Currently optional is defined with different defaults for the Pydantic models compared to the internal_schema dictionary",
62
62
  )
@@ -83,7 +83,7 @@ class SchemaAttribute(BaseModel):
83
83
  @property
84
84
  def type_annotation(self) -> str:
85
85
  if self.optional_in_model:
86
- return f"Optional[{self.object_kind}]"
86
+ return f"{self.object_kind} | None"
87
87
 
88
88
  return self.object_kind
89
89
 
@@ -150,8 +150,8 @@ class SchemaAttribute(BaseModel):
150
150
  class SchemaRelationship(BaseModel):
151
151
  name: str
152
152
  peer: str
153
- description: Optional[str] = None
154
- kind: Optional[str] = None
153
+ description: str | None = None
154
+ kind: str | None = None
155
155
  identifier: str
156
156
  cardinality: str
157
157
  branch: str
@@ -166,7 +166,7 @@ class SchemaNode(BaseModel):
166
166
  namespace: str
167
167
  branch: str
168
168
  include_in_menu: bool
169
- default_filter: Optional[str] = None
169
+ default_filter: str | None = None
170
170
  attributes: list[SchemaAttribute]
171
171
  relationships: list[SchemaRelationship]
172
172
  display_labels: list[str]
@@ -199,7 +199,7 @@ class SchemaNode(BaseModel):
199
199
 
200
200
  @dataclass
201
201
  class InternalSchema:
202
- version: Optional[str]
202
+ version: str | None
203
203
  nodes: list[SchemaNode]
204
204
 
205
205
  def to_dict(self) -> dict[str, Any]:
@@ -1,5 +1,4 @@
1
1
  import re
2
- from typing import Optional
3
2
 
4
3
  from pydantic import field_validator
5
4
 
@@ -10,9 +9,9 @@ HTML_COLOR = re.compile(r"#[0-9a-fA-F]{6}\b")
10
9
 
11
10
  class DropdownChoice(HashableModel):
12
11
  name: str
13
- description: Optional[str] = None
14
- color: Optional[str] = None
15
- label: Optional[str] = None
12
+ description: str | None = None
13
+ color: str | None = None
14
+ label: str | None = None
16
15
 
17
16
  _sort_by: list[str] = ["name"]
18
17
 
@@ -2,21 +2,18 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any, Optional
5
+ from typing import Any
6
6
 
7
7
  from pydantic import Field
8
8
 
9
- from infrahub.core.constants import AllowOverrideType, HashableModelState
9
+ from infrahub.core.constants import AllowOverrideType, BranchSupportType, HashableModelState
10
10
  from infrahub.core.models import HashableModel
11
11
  from infrahub.core.schema.computed_attribute import ComputedAttribute # noqa: TC001
12
12
  from infrahub.core.schema.dropdown import DropdownChoice # noqa: TC001
13
13
 
14
- if TYPE_CHECKING:
15
- from infrahub.core.constants import BranchSupportType
16
-
17
14
 
18
15
  class GeneratedAttributeSchema(HashableModel):
19
- id: Optional[str] = Field(
16
+ id: str | None = Field(
20
17
  default=None, description="The ID of the attribute", json_schema_extra={"update": "not_applicable"}
21
18
  )
22
19
  name: str = Field(
@@ -30,43 +27,43 @@ class GeneratedAttributeSchema(HashableModel):
30
27
  kind: str = Field(
31
28
  ..., description="Defines the type of the attribute.", json_schema_extra={"update": "validate_constraint"}
32
29
  )
33
- enum: Optional[list] = Field(
30
+ enum: list | None = Field(
34
31
  default=None,
35
32
  description="Define a list of valid values for the attribute.",
36
33
  json_schema_extra={"update": "validate_constraint"},
37
34
  )
38
- computed_attribute: Optional[ComputedAttribute] = Field(
35
+ computed_attribute: ComputedAttribute | None = Field(
39
36
  default=None,
40
37
  description="Defines how the value of this attribute will be populated.",
41
38
  json_schema_extra={"update": "allowed"},
42
39
  )
43
- choices: Optional[list[DropdownChoice]] = Field(
40
+ choices: list[DropdownChoice] | None = Field(
44
41
  default=None,
45
42
  description="Define a list of valid choices for a dropdown attribute.",
46
43
  json_schema_extra={"update": "validate_constraint"},
47
44
  )
48
- regex: Optional[str] = Field(
45
+ regex: str | None = Field(
49
46
  default=None,
50
47
  description="Regex uses to limit the characters allowed in for the attributes.",
51
48
  json_schema_extra={"update": "validate_constraint"},
52
49
  )
53
- max_length: Optional[int] = Field(
50
+ max_length: int | None = Field(
54
51
  default=None,
55
52
  description="Set a maximum number of characters allowed for a given attribute.",
56
53
  json_schema_extra={"update": "validate_constraint"},
57
54
  )
58
- min_length: Optional[int] = Field(
55
+ min_length: int | None = Field(
59
56
  default=None,
60
57
  description="Set a minimum number of characters allowed for a given attribute.",
61
58
  json_schema_extra={"update": "validate_constraint"},
62
59
  )
63
- label: Optional[str] = Field(
60
+ label: str | None = Field(
64
61
  default=None,
65
62
  description="Human friendly representation of the name. Will be autogenerated if not provided",
66
63
  max_length=32,
67
64
  json_schema_extra={"update": "allowed"},
68
65
  )
69
- description: Optional[str] = Field(
66
+ description: str | None = Field(
70
67
  default=None,
71
68
  description="Short description of the attribute.",
72
69
  max_length=128,
@@ -87,17 +84,17 @@ class GeneratedAttributeSchema(HashableModel):
87
84
  description="Indicate if this attribute is mandatory or optional.",
88
85
  json_schema_extra={"update": "validate_constraint"},
89
86
  )
90
- branch: Optional[BranchSupportType] = Field(
87
+ branch: BranchSupportType | None = Field(
91
88
  default=None,
92
89
  description="Type of branch support for the attribute, if not defined it will be inherited from the node.",
93
90
  json_schema_extra={"update": "not_supported"},
94
91
  )
95
- order_weight: Optional[int] = Field(
92
+ order_weight: int | None = Field(
96
93
  default=None,
97
94
  description="Number used to order the attribute in the frontend (table and view). Lowest value will be ordered first.",
98
95
  json_schema_extra={"update": "allowed"},
99
96
  )
100
- default_value: Optional[Any] = Field(
97
+ default_value: Any | None = Field(
101
98
  default=None, description="Default value of the attribute.", json_schema_extra={"update": "allowed"}
102
99
  )
103
100
  inherited: bool = Field(
@@ -115,7 +112,7 @@ class GeneratedAttributeSchema(HashableModel):
115
112
  description="Type of allowed override for the attribute.",
116
113
  json_schema_extra={"update": "allowed"},
117
114
  )
118
- deprecation: Optional[str] = Field(
115
+ deprecation: str | None = Field(
119
116
  default=None,
120
117
  description="Mark attribute as deprecated and provide a user-friendly message to display",
121
118
  max_length=128,
@@ -2,8 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Optional
6
-
7
5
  from pydantic import Field
8
6
 
9
7
  from infrahub.core.constants import BranchSupportType, HashableModelState
@@ -13,7 +11,7 @@ from infrahub.core.schema.relationship_schema import RelationshipSchema # noqa:
13
11
 
14
12
 
15
13
  class GeneratedBaseNodeSchema(HashableModel):
16
- id: Optional[str] = Field(
14
+ id: str | None = Field(
17
15
  default=None, description="The ID of the node", json_schema_extra={"update": "not_applicable"}
18
16
  )
19
17
  name: str = Field(
@@ -32,13 +30,13 @@ class GeneratedBaseNodeSchema(HashableModel):
32
30
  max_length=32,
33
31
  json_schema_extra={"update": "migration_required"},
34
32
  )
35
- description: Optional[str] = Field(
33
+ description: str | None = Field(
36
34
  default=None,
37
35
  description="Short description of the model, will be visible in the frontend.",
38
36
  max_length=128,
39
37
  json_schema_extra={"update": "allowed"},
40
38
  )
41
- label: Optional[str] = Field(
39
+ label: str | None = Field(
42
40
  default=None,
43
41
  description="Human friendly representation of the name/kind",
44
42
  max_length=64,
@@ -49,48 +47,48 @@ class GeneratedBaseNodeSchema(HashableModel):
49
47
  description="Type of branch support for the model.",
50
48
  json_schema_extra={"update": "not_supported"},
51
49
  )
52
- default_filter: Optional[str] = Field(
50
+ default_filter: str | None = Field(
53
51
  default=None,
54
52
  description="Default filter used to search for a node in addition to its ID. (deprecated: please use human_friendly_id instead)",
55
53
  pattern=r"^[a-z0-9\_]+$",
56
54
  json_schema_extra={"update": "allowed"},
57
55
  )
58
- human_friendly_id: Optional[list[str]] = Field(
56
+ human_friendly_id: list[str] | None = Field(
59
57
  default=None,
60
58
  description="Human friendly and unique identifier for the object.",
61
59
  json_schema_extra={"update": "allowed"},
62
60
  )
63
- display_labels: Optional[list[str]] = Field(
61
+ display_labels: list[str] | None = Field(
64
62
  default=None,
65
63
  description="List of attributes to use to generate the display label",
66
64
  json_schema_extra={"update": "allowed"},
67
65
  )
68
- include_in_menu: Optional[bool] = Field(
66
+ include_in_menu: bool | None = Field(
69
67
  default=None,
70
68
  description="Defines if objects of this kind should be included in the menu.",
71
69
  json_schema_extra={"update": "allowed"},
72
70
  )
73
- menu_placement: Optional[str] = Field(
71
+ menu_placement: str | None = Field(
74
72
  default=None,
75
73
  description="Defines where in the menu this object should be placed.",
76
74
  json_schema_extra={"update": "allowed"},
77
75
  )
78
- icon: Optional[str] = Field(
76
+ icon: str | None = Field(
79
77
  default=None,
80
78
  description="Defines the icon to use in the menu. Must be a valid value from the MDI library https://icon-sets.iconify.design/mdi/",
81
79
  json_schema_extra={"update": "allowed"},
82
80
  )
83
- order_by: Optional[list[str]] = Field(
81
+ order_by: list[str] | None = Field(
84
82
  default=None,
85
83
  description="List of attributes to use to order the results by default",
86
84
  json_schema_extra={"update": "allowed"},
87
85
  )
88
- uniqueness_constraints: Optional[list[list[str]]] = Field(
86
+ uniqueness_constraints: list[list[str]] | None = Field(
89
87
  default=None,
90
88
  description="List of multi-element uniqueness constraints that can combine relationships and attributes",
91
89
  json_schema_extra={"update": "validate_constraint"},
92
90
  )
93
- documentation: Optional[str] = Field(
91
+ documentation: str | None = Field(
94
92
  default=None,
95
93
  description="Link to a documentation associated with this object, can be internal or external.",
96
94
  json_schema_extra={"update": "allowed"},
@@ -2,8 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Optional
6
-
7
5
  from pydantic import Field
8
6
 
9
7
  from infrahub.core.schema.basenode_schema import BaseNodeSchema
@@ -25,17 +23,17 @@ class GeneratedNodeSchema(BaseNodeSchema):
25
23
  description="Indicate if an object template schema should be generated for this schema",
26
24
  json_schema_extra={"update": "allowed"},
27
25
  )
28
- hierarchy: Optional[str] = Field(
26
+ hierarchy: str | None = Field(
29
27
  default=None,
30
28
  description="Internal value to track the name of the Hierarchy, must match the name of a Generic supporting hierarchical mode",
31
29
  json_schema_extra={"update": "validate_constraint"},
32
30
  )
33
- parent: Optional[str] = Field(
31
+ parent: str | None = Field(
34
32
  default=None,
35
33
  description="Expected Kind for the parent node in a Hierarchy, default to the main generic defined if not defined.",
36
34
  json_schema_extra={"update": "validate_constraint"},
37
35
  )
38
- children: Optional[str] = Field(
36
+ children: str | None = Field(
39
37
  default=None,
40
38
  description="Expected Kind for the children nodes in a Hierarchy, default to the main generic defined if not defined.",
41
39
  json_schema_extra={"update": "validate_constraint"},
@@ -2,8 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Optional
6
-
7
5
  from pydantic import Field
8
6
 
9
7
  from infrahub.core.constants import (
@@ -19,7 +17,7 @@ from infrahub.core.models import HashableModel
19
17
 
20
18
 
21
19
  class GeneratedRelationshipSchema(HashableModel):
22
- id: Optional[str] = Field(
20
+ id: str | None = Field(
23
21
  default=None, description="The ID of the relationship schema", json_schema_extra={"update": "not_applicable"}
24
22
  )
25
23
  name: str = Field(
@@ -41,19 +39,19 @@ class GeneratedRelationshipSchema(HashableModel):
41
39
  description="Defines the type of the relationship.",
42
40
  json_schema_extra={"update": "allowed"},
43
41
  )
44
- label: Optional[str] = Field(
42
+ label: str | None = Field(
45
43
  default=None,
46
44
  description="Human friendly representation of the name. Will be autogenerated if not provided",
47
45
  max_length=32,
48
46
  json_schema_extra={"update": "allowed"},
49
47
  )
50
- description: Optional[str] = Field(
48
+ description: str | None = Field(
51
49
  default=None,
52
50
  description="Short description of the relationship.",
53
51
  max_length=128,
54
52
  json_schema_extra={"update": "allowed"},
55
53
  )
56
- identifier: Optional[str] = Field(
54
+ identifier: str | None = Field(
57
55
  default=None,
58
56
  description="Unique identifier of the relationship within a model, identifiers must match to traverse a relationship on both direction.",
59
57
  pattern=r"^[a-z0-9\_]+$",
@@ -75,7 +73,7 @@ class GeneratedRelationshipSchema(HashableModel):
75
73
  description="Defines the maximum objects allowed on the other side of the relationship.",
76
74
  json_schema_extra={"update": "validate_constraint"},
77
75
  )
78
- order_weight: Optional[int] = Field(
76
+ order_weight: int | None = Field(
79
77
  default=None,
80
78
  description="Number used to order the relationship in the frontend (table and view). Lowest value will be ordered first.",
81
79
  json_schema_extra={"update": "allowed"},
@@ -85,7 +83,7 @@ class GeneratedRelationshipSchema(HashableModel):
85
83
  description="Indicate if this relationship is mandatory or optional.",
86
84
  json_schema_extra={"update": "validate_constraint"},
87
85
  )
88
- branch: Optional[BranchSupportType] = Field(
86
+ branch: BranchSupportType | None = Field(
89
87
  default=None,
90
88
  description="Type of branch support for the relatioinship, if not defined it will be determine based both peers.",
91
89
  json_schema_extra={"update": "not_supported"},
@@ -100,7 +98,7 @@ class GeneratedRelationshipSchema(HashableModel):
100
98
  description="Defines the direction of the relationship, Unidirectional relationship are required when the same model is on both side.",
101
99
  json_schema_extra={"update": "not_supported"},
102
100
  )
103
- hierarchical: Optional[str] = Field(
101
+ hierarchical: str | None = Field(
104
102
  default=None,
105
103
  description="Internal attribute to track the type of hierarchy this relationship is part of, must match a valid Generic Kind",
106
104
  json_schema_extra={"update": "not_supported"},
@@ -110,7 +108,7 @@ class GeneratedRelationshipSchema(HashableModel):
110
108
  description="Expected state of the relationship after loading the schema",
111
109
  json_schema_extra={"update": "not_applicable"},
112
110
  )
113
- on_delete: Optional[RelationshipDeleteBehavior] = Field(
111
+ on_delete: RelationshipDeleteBehavior | None = Field(
114
112
  default=None,
115
113
  description="Default is no-action. If cascade, related node(s) are deleted when this node is deleted.",
116
114
  json_schema_extra={"update": "allowed"},
@@ -125,7 +123,7 @@ class GeneratedRelationshipSchema(HashableModel):
125
123
  description="Set the relationship as read-only, users won't be able to change its value.",
126
124
  json_schema_extra={"update": "allowed"},
127
125
  )
128
- deprecation: Optional[str] = Field(
126
+ deprecation: str | None = Field(
129
127
  default=None,
130
128
  description="Mark relationship as deprecated and provide a user-friendly message to display",
131
129
  max_length=128,
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Optional, Union
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from .generated.genericnode_schema import GeneratedGenericSchema
6
6
 
@@ -28,7 +28,7 @@ class GenericSchema(GeneratedGenericSchema):
28
28
  def is_template_schema(self) -> bool:
29
29
  return False
30
30
 
31
- def get_hierarchy_schema(self, db: InfrahubDatabase, branch: Optional[Union[Branch, str]] = None) -> GenericSchema: # noqa: ARG002
31
+ def get_hierarchy_schema(self, db: InfrahubDatabase, branch: Branch | str | None = None) -> GenericSchema: # noqa: ARG002
32
32
  if self.hierarchical:
33
33
  return self
34
34
 
@@ -251,7 +251,7 @@ class SchemaManager(NodeManager):
251
251
 
252
252
  branch = await registry.get_branch(branch=branch, db=db)
253
253
 
254
- for item_kind in schema.node_names + schema.generic_names:
254
+ for item_kind in schema.node_names + schema.generic_names_without_templates:
255
255
  if limit and item_kind not in limit:
256
256
  continue
257
257
  item = schema.get(name=item_kind, duplicate=False)
@@ -295,15 +295,21 @@ class SchemaManager(NodeManager):
295
295
  new_node.attributes = []
296
296
 
297
297
  for item in node.attributes:
298
- new_attr = await self.create_attribute_in_db(
299
- schema=attribute_schema, item=item, parent=obj, branch=branch, db=db
300
- )
298
+ if item.inherited is False:
299
+ new_attr = await self.create_attribute_in_db(
300
+ schema=attribute_schema, item=item, parent=obj, branch=branch, db=db
301
+ )
302
+ else:
303
+ new_attr = item.duplicate()
301
304
  new_node.attributes.append(new_attr)
302
305
 
303
306
  for item in node.relationships:
304
- new_rel = await self.create_relationship_in_db(
305
- schema=relationship_schema, item=item, parent=obj, branch=branch, db=db
306
- )
307
+ if item.inherited is False:
308
+ new_rel = await self.create_relationship_in_db(
309
+ schema=relationship_schema, item=item, parent=obj, branch=branch, db=db
310
+ )
311
+ else:
312
+ new_rel = item.duplicate()
307
313
  new_node.relationships.append(new_rel)
308
314
 
309
315
  # Save back the node with the newly created IDs in the SchemaManager
@@ -465,7 +471,8 @@ class SchemaManager(NodeManager):
465
471
 
466
472
  if diff_attributes:
467
473
  for item in node.local_attributes:
468
- if item.name in diff_attributes.added:
474
+ # if item is in changed and has no ID, then it is being overridden from a generic and must be added
475
+ if item.name in diff_attributes.added or item.name in diff_attributes.changed and item.id is None:
469
476
  created_item = await self.create_attribute_in_db(
470
477
  schema=attribute_schema, item=item, branch=branch, db=db, parent=obj
471
478
  )
@@ -484,7 +491,8 @@ class SchemaManager(NodeManager):
484
491
 
485
492
  if diff_relationships:
486
493
  for item in node.local_relationships:
487
- if item.name in diff_relationships.added:
494
+ # if item is in changed and has no ID, then it is being overridden from a generic and must be added
495
+ if item.name in diff_relationships.added or item.name in diff_relationships.changed and item.id is None:
488
496
  created_rel = await self.create_relationship_in_db(
489
497
  schema=relationship_schema, item=item, branch=branch, db=db, parent=obj
490
498
  )
@@ -715,6 +723,9 @@ class SchemaManager(NodeManager):
715
723
  for rel in await rm.get(db=db):
716
724
  item = await rel.get_peer(db=db)
717
725
  item_data = {"id": item.id}
726
+ inherited_attr = getattr(item, "inherited", None)
727
+ if inherited_attr and getattr(inherited_attr, "value", False) is True:
728
+ continue
718
729
  for item_name in item._attributes:
719
730
  item_attr = getattr(item, item_name)
720
731
  item_data[item_name] = item_attr.get_value()
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Optional, Union
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from infrahub.core.constants import AllowOverrideType, InfrahubKind
6
6
 
@@ -98,6 +98,7 @@ class NodeSchema(GeneratedNodeSchema):
98
98
  continue
99
99
 
100
100
  new_attribute = attribute.duplicate()
101
+ new_attribute.id = None
101
102
  new_attribute.inherited = True
102
103
 
103
104
  if attribute.name not in existing_inherited_fields:
@@ -111,6 +112,7 @@ class NodeSchema(GeneratedNodeSchema):
111
112
  continue
112
113
 
113
114
  new_relationship = relationship.duplicate()
115
+ new_relationship.id = None
114
116
  new_relationship.inherited = True
115
117
 
116
118
  if relationship.name not in existing_inherited_fields:
@@ -119,7 +121,7 @@ class NodeSchema(GeneratedNodeSchema):
119
121
  item_idx = existing_inherited_relationships[relationship.name]
120
122
  self.relationships[item_idx].update_from_generic(other=new_relationship)
121
123
 
122
- def get_hierarchy_schema(self, db: InfrahubDatabase, branch: Optional[Union[Branch, str]] = None) -> GenericSchema:
124
+ def get_hierarchy_schema(self, db: InfrahubDatabase, branch: Branch | str | None = None) -> GenericSchema:
123
125
  if not self.hierarchy:
124
126
  raise ValueError("The node is not part of a hierarchy")
125
127
  schema = db.schema.get(name=self.hierarchy, branch=branch)