infrahub-server 1.6.2__py3-none-any.whl → 1.7.0__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 (253) hide show
  1. infrahub/actions/tasks.py +4 -2
  2. infrahub/api/exceptions.py +2 -2
  3. infrahub/api/schema.py +3 -1
  4. infrahub/artifacts/tasks.py +1 -0
  5. infrahub/auth.py +2 -2
  6. infrahub/cli/db.py +54 -28
  7. infrahub/computed_attribute/gather.py +3 -4
  8. infrahub/computed_attribute/tasks.py +23 -6
  9. infrahub/config.py +8 -0
  10. infrahub/constants/enums.py +12 -0
  11. infrahub/core/account.py +12 -9
  12. infrahub/core/attribute.py +106 -108
  13. infrahub/core/branch/models.py +44 -71
  14. infrahub/core/branch/tasks.py +5 -3
  15. infrahub/core/changelog/diff.py +1 -20
  16. infrahub/core/changelog/models.py +0 -7
  17. infrahub/core/constants/__init__.py +17 -0
  18. infrahub/core/constants/database.py +0 -1
  19. infrahub/core/constants/schema.py +0 -1
  20. infrahub/core/convert_object_type/repository_conversion.py +3 -4
  21. infrahub/core/diff/branch_differ.py +1 -1
  22. infrahub/core/diff/conflict_transferer.py +1 -1
  23. infrahub/core/diff/data_check_synchronizer.py +4 -3
  24. infrahub/core/diff/enricher/cardinality_one.py +2 -2
  25. infrahub/core/diff/enricher/hierarchy.py +1 -1
  26. infrahub/core/diff/enricher/labels.py +1 -1
  27. infrahub/core/diff/merger/merger.py +28 -2
  28. infrahub/core/diff/merger/serializer.py +3 -10
  29. infrahub/core/diff/model/diff.py +1 -1
  30. infrahub/core/diff/query/merge.py +376 -135
  31. infrahub/core/diff/repository/repository.py +3 -1
  32. infrahub/core/graph/__init__.py +1 -1
  33. infrahub/core/graph/constraints.py +3 -3
  34. infrahub/core/graph/schema.py +2 -12
  35. infrahub/core/ipam/reconciler.py +8 -6
  36. infrahub/core/ipam/utilization.py +8 -15
  37. infrahub/core/manager.py +133 -152
  38. infrahub/core/merge.py +1 -1
  39. infrahub/core/metadata/__init__.py +0 -0
  40. infrahub/core/metadata/interface.py +37 -0
  41. infrahub/core/metadata/model.py +31 -0
  42. infrahub/core/metadata/query/__init__.py +0 -0
  43. infrahub/core/metadata/query/node_metadata.py +301 -0
  44. infrahub/core/migrations/graph/__init__.py +4 -0
  45. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -12
  46. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -12
  47. infrahub/core/migrations/graph/m017_add_core_profile.py +5 -2
  48. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -1
  49. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +0 -10
  50. infrahub/core/migrations/graph/m020_duplicate_edges.py +0 -8
  51. infrahub/core/migrations/graph/m025_uniqueness_nulls.py +2 -1
  52. infrahub/core/migrations/graph/m026_0000_prefix_fix.py +2 -1
  53. infrahub/core/migrations/graph/m029_duplicates_cleanup.py +0 -1
  54. infrahub/core/migrations/graph/m031_check_number_attributes.py +2 -2
  55. infrahub/core/migrations/graph/m038_redo_0000_prefix_fix.py +2 -1
  56. infrahub/core/migrations/graph/m041_deleted_dup_edges.py +1 -1
  57. infrahub/core/migrations/graph/m049_remove_is_visible_relationship.py +53 -0
  58. infrahub/core/migrations/graph/m050_backfill_vertex_metadata.py +168 -0
  59. infrahub/core/migrations/query/__init__.py +2 -2
  60. infrahub/core/migrations/query/attribute_add.py +17 -6
  61. infrahub/core/migrations/query/attribute_remove.py +19 -5
  62. infrahub/core/migrations/query/attribute_rename.py +21 -5
  63. infrahub/core/migrations/query/node_duplicate.py +19 -4
  64. infrahub/core/migrations/query/schema_attribute_update.py +1 -1
  65. infrahub/core/migrations/schema/attribute_kind_update.py +26 -6
  66. infrahub/core/migrations/schema/attribute_name_update.py +1 -1
  67. infrahub/core/migrations/schema/attribute_supports_profile.py +5 -3
  68. infrahub/core/migrations/schema/models.py +3 -0
  69. infrahub/core/migrations/schema/node_attribute_add.py +5 -2
  70. infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
  71. infrahub/core/migrations/schema/node_kind_update.py +1 -1
  72. infrahub/core/migrations/schema/node_remove.py +24 -2
  73. infrahub/core/migrations/schema/tasks.py +4 -1
  74. infrahub/core/migrations/shared.py +13 -6
  75. infrahub/core/models.py +6 -6
  76. infrahub/core/node/__init__.py +157 -58
  77. infrahub/core/node/base.py +9 -5
  78. infrahub/core/node/create.py +7 -3
  79. infrahub/core/node/delete_validator.py +1 -1
  80. infrahub/core/node/standard.py +100 -14
  81. infrahub/core/order.py +30 -0
  82. infrahub/core/property.py +0 -1
  83. infrahub/core/protocols.py +1 -0
  84. infrahub/core/protocols_base.py +10 -2
  85. infrahub/core/query/__init__.py +11 -6
  86. infrahub/core/query/attribute.py +164 -49
  87. infrahub/core/query/branch.py +58 -70
  88. infrahub/core/query/delete.py +1 -1
  89. infrahub/core/query/diff.py +7 -7
  90. infrahub/core/query/ipam.py +104 -43
  91. infrahub/core/query/node.py +1072 -281
  92. infrahub/core/query/relationship.py +531 -325
  93. infrahub/core/query/resource_manager.py +107 -18
  94. infrahub/core/query/standard_node.py +25 -5
  95. infrahub/core/query/utils.py +2 -4
  96. infrahub/core/relationship/constraints/count.py +1 -1
  97. infrahub/core/relationship/constraints/peer_kind.py +1 -1
  98. infrahub/core/relationship/constraints/peer_parent.py +1 -1
  99. infrahub/core/relationship/constraints/peer_relatives.py +1 -1
  100. infrahub/core/relationship/constraints/profiles_kind.py +1 -1
  101. infrahub/core/relationship/constraints/profiles_removal.py +168 -0
  102. infrahub/core/relationship/model.py +293 -139
  103. infrahub/core/schema/attribute_parameters.py +28 -1
  104. infrahub/core/schema/attribute_schema.py +11 -17
  105. infrahub/core/schema/basenode_schema.py +3 -0
  106. infrahub/core/schema/definitions/core/__init__.py +8 -2
  107. infrahub/core/schema/definitions/core/account.py +10 -10
  108. infrahub/core/schema/definitions/core/artifact.py +14 -8
  109. infrahub/core/schema/definitions/core/check.py +10 -4
  110. infrahub/core/schema/definitions/core/generator.py +26 -6
  111. infrahub/core/schema/definitions/core/graphql_query.py +1 -1
  112. infrahub/core/schema/definitions/core/group.py +9 -2
  113. infrahub/core/schema/definitions/core/ipam.py +80 -10
  114. infrahub/core/schema/definitions/core/menu.py +41 -7
  115. infrahub/core/schema/definitions/core/permission.py +16 -2
  116. infrahub/core/schema/definitions/core/profile.py +16 -2
  117. infrahub/core/schema/definitions/core/propose_change.py +24 -4
  118. infrahub/core/schema/definitions/core/propose_change_comment.py +23 -11
  119. infrahub/core/schema/definitions/core/propose_change_validator.py +50 -21
  120. infrahub/core/schema/definitions/core/repository.py +10 -0
  121. infrahub/core/schema/definitions/core/resource_pool.py +8 -1
  122. infrahub/core/schema/definitions/core/template.py +19 -2
  123. infrahub/core/schema/definitions/core/transform.py +11 -5
  124. infrahub/core/schema/definitions/core/webhook.py +27 -9
  125. infrahub/core/schema/manager.py +63 -43
  126. infrahub/core/schema/relationship_schema.py +6 -2
  127. infrahub/core/schema/schema_branch.py +115 -11
  128. infrahub/core/task/task.py +4 -2
  129. infrahub/core/utils.py +3 -25
  130. infrahub/core/validators/aggregated_checker.py +1 -1
  131. infrahub/core/validators/attribute/choices.py +1 -1
  132. infrahub/core/validators/attribute/enum.py +1 -1
  133. infrahub/core/validators/attribute/kind.py +6 -3
  134. infrahub/core/validators/attribute/length.py +1 -1
  135. infrahub/core/validators/attribute/min_max.py +1 -1
  136. infrahub/core/validators/attribute/number_pool.py +1 -1
  137. infrahub/core/validators/attribute/optional.py +1 -1
  138. infrahub/core/validators/attribute/regex.py +1 -1
  139. infrahub/core/validators/determiner.py +3 -3
  140. infrahub/core/validators/node/attribute.py +1 -1
  141. infrahub/core/validators/node/relationship.py +1 -1
  142. infrahub/core/validators/relationship/peer.py +1 -1
  143. infrahub/database/__init__.py +4 -4
  144. infrahub/dependencies/builder/constraint/grouped/node_runner.py +2 -0
  145. infrahub/dependencies/builder/constraint/relationship_manager/profiles_removal.py +8 -0
  146. infrahub/dependencies/registry.py +2 -0
  147. infrahub/display_labels/tasks.py +12 -3
  148. infrahub/git/integrator.py +18 -18
  149. infrahub/git/tasks.py +1 -1
  150. infrahub/git/utils.py +1 -1
  151. infrahub/graphql/app.py +2 -2
  152. infrahub/graphql/constants.py +3 -0
  153. infrahub/graphql/context.py +1 -1
  154. infrahub/graphql/field_extractor.py +1 -1
  155. infrahub/graphql/initialization.py +11 -0
  156. infrahub/graphql/loaders/account.py +134 -0
  157. infrahub/graphql/loaders/node.py +5 -12
  158. infrahub/graphql/loaders/peers.py +5 -7
  159. infrahub/graphql/manager.py +175 -21
  160. infrahub/graphql/metadata.py +91 -0
  161. infrahub/graphql/mutations/account.py +6 -6
  162. infrahub/graphql/mutations/attribute.py +0 -2
  163. infrahub/graphql/mutations/branch.py +9 -5
  164. infrahub/graphql/mutations/computed_attribute.py +1 -1
  165. infrahub/graphql/mutations/display_label.py +1 -1
  166. infrahub/graphql/mutations/hfid.py +1 -1
  167. infrahub/graphql/mutations/ipam.py +4 -6
  168. infrahub/graphql/mutations/main.py +9 -4
  169. infrahub/graphql/mutations/profile.py +16 -22
  170. infrahub/graphql/mutations/proposed_change.py +4 -4
  171. infrahub/graphql/mutations/relationship.py +40 -10
  172. infrahub/graphql/mutations/repository.py +14 -12
  173. infrahub/graphql/mutations/schema.py +2 -2
  174. infrahub/graphql/order.py +14 -0
  175. infrahub/graphql/queries/branch.py +62 -6
  176. infrahub/graphql/queries/diff/tree.py +5 -5
  177. infrahub/graphql/queries/resource_manager.py +25 -24
  178. infrahub/graphql/resolvers/account_metadata.py +84 -0
  179. infrahub/graphql/resolvers/ipam.py +6 -8
  180. infrahub/graphql/resolvers/many_relationship.py +77 -35
  181. infrahub/graphql/resolvers/resolver.py +59 -14
  182. infrahub/graphql/resolvers/single_relationship.py +87 -23
  183. infrahub/graphql/subscription/graphql_query.py +2 -0
  184. infrahub/graphql/types/__init__.py +0 -1
  185. infrahub/graphql/types/attribute.py +10 -5
  186. infrahub/graphql/types/branch.py +40 -53
  187. infrahub/graphql/types/enums.py +3 -0
  188. infrahub/graphql/types/metadata.py +28 -0
  189. infrahub/graphql/types/node.py +22 -2
  190. infrahub/graphql/types/relationship.py +10 -2
  191. infrahub/graphql/types/standard_node.py +12 -7
  192. infrahub/hfid/tasks.py +12 -3
  193. infrahub/lock.py +7 -0
  194. infrahub/menu/repository.py +1 -1
  195. infrahub/patch/queries/base.py +1 -1
  196. infrahub/pools/number.py +1 -8
  197. infrahub/profiles/gather.py +56 -0
  198. infrahub/profiles/mandatory_fields_checker.py +116 -0
  199. infrahub/profiles/models.py +66 -0
  200. infrahub/profiles/node_applier.py +154 -13
  201. infrahub/profiles/queries/get_profile_data.py +143 -31
  202. infrahub/profiles/tasks.py +79 -27
  203. infrahub/profiles/triggers.py +22 -0
  204. infrahub/proposed_change/action_checker.py +1 -1
  205. infrahub/proposed_change/tasks.py +4 -1
  206. infrahub/services/__init__.py +1 -1
  207. infrahub/services/adapters/cache/nats.py +1 -1
  208. infrahub/services/adapters/cache/redis.py +7 -0
  209. infrahub/tasks/artifact.py +1 -0
  210. infrahub/transformations/tasks.py +2 -2
  211. infrahub/trigger/catalogue.py +2 -0
  212. infrahub/trigger/models.py +1 -0
  213. infrahub/trigger/setup.py +3 -3
  214. infrahub/trigger/tasks.py +3 -0
  215. infrahub/validators/tasks.py +1 -0
  216. infrahub/webhook/gather.py +1 -1
  217. infrahub/webhook/models.py +1 -1
  218. infrahub/webhook/tasks.py +23 -7
  219. infrahub/workers/dependencies.py +9 -3
  220. infrahub/workers/infrahub_async.py +13 -4
  221. infrahub/workflows/catalogue.py +19 -0
  222. infrahub_sdk/analyzer.py +2 -2
  223. infrahub_sdk/branch.py +12 -39
  224. infrahub_sdk/checks.py +4 -4
  225. infrahub_sdk/client.py +36 -0
  226. infrahub_sdk/ctl/cli_commands.py +2 -1
  227. infrahub_sdk/ctl/graphql.py +15 -4
  228. infrahub_sdk/ctl/utils.py +2 -2
  229. infrahub_sdk/enums.py +6 -0
  230. infrahub_sdk/graphql/renderers.py +21 -0
  231. infrahub_sdk/graphql/utils.py +85 -0
  232. infrahub_sdk/node/attribute.py +12 -2
  233. infrahub_sdk/node/constants.py +12 -0
  234. infrahub_sdk/node/metadata.py +69 -0
  235. infrahub_sdk/node/node.py +65 -14
  236. infrahub_sdk/node/property.py +3 -0
  237. infrahub_sdk/node/related_node.py +37 -5
  238. infrahub_sdk/node/relationship.py +18 -1
  239. infrahub_sdk/operation.py +2 -2
  240. infrahub_sdk/schema/repository.py +1 -2
  241. infrahub_sdk/transforms.py +2 -2
  242. infrahub_sdk/types.py +18 -2
  243. {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/METADATA +17 -16
  244. {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/RECORD +252 -231
  245. infrahub_testcontainers/container.py +3 -3
  246. infrahub_testcontainers/docker-compose-cluster.test.yml +7 -7
  247. infrahub_testcontainers/docker-compose.test.yml +13 -5
  248. infrahub_testcontainers/models.py +3 -3
  249. infrahub_testcontainers/performance_test.py +1 -1
  250. infrahub/graphql/models.py +0 -6
  251. {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/WHEEL +0 -0
  252. {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/entry_points.txt +0 -0
  253. {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import sys
4
- from typing import Self
4
+ from typing import Any, Self
5
5
 
6
6
  from pydantic import ConfigDict, Field, model_validator
7
7
 
@@ -24,6 +24,33 @@ def get_attribute_parameters_class_for_kind(kind: str) -> type[AttributeParamete
24
24
  class AttributeParameters(HashableModel):
25
25
  model_config = ConfigDict(extra="forbid")
26
26
 
27
+ @classmethod
28
+ def convert_from(cls, source: AttributeParameters) -> Self:
29
+ """Convert from another AttributeParameters subclass.
30
+
31
+ Args:
32
+ source: The source AttributeParameters instance to convert from
33
+
34
+ Returns:
35
+ A new instance of the target class with compatible fields populated
36
+ """
37
+ source_data = source.model_dump()
38
+ return cls.convert_from_dict(source_data=source_data)
39
+
40
+ @classmethod
41
+ def convert_from_dict(cls, source_data: dict[str, Any]) -> Self:
42
+ """Convert from a dictionary to the target class.
43
+
44
+ Args:
45
+ source_data: The source dictionary to convert from
46
+
47
+ Returns:
48
+ A new instance of the target class with compatible fields populated
49
+ """
50
+ target_fields = set(cls.model_fields.keys())
51
+ filtered_data = {k: v for k, v in source_data.items() if k in target_fields}
52
+ return cls(**filtered_data)
53
+
27
54
 
28
55
  class TextAttributeParameters(AttributeParameters):
29
56
  regex: str | None = Field(
@@ -70,7 +70,7 @@ class AttributeSchema(GeneratedAttributeSchema):
70
70
 
71
71
  @property
72
72
  def support_profiles(self) -> bool:
73
- return self.read_only is False and self.optional is True
73
+ return self.read_only is False and self.unique is False
74
74
 
75
75
  def get_id(self) -> str:
76
76
  if self.id is None:
@@ -114,13 +114,20 @@ class AttributeSchema(GeneratedAttributeSchema):
114
114
  @field_validator("parameters", mode="before")
115
115
  @classmethod
116
116
  def set_parameters_type(cls, value: Any, info: ValidationInfo) -> Any:
117
- """Override parameters class if using base AttributeParameters class and should be using a subclass"""
117
+ """Override parameters class if using base AttributeParameters class and should be using a subclass.
118
+
119
+ This validator handles parameter type conversion when an attribute's kind changes.
120
+ Fields from the source that don't exist in the target are silently dropped.
121
+ Fields with the same name in both classes are preserved.
122
+ """
118
123
  kind = info.data["kind"]
119
124
  expected_parameters_class = get_attribute_parameters_class_for_kind(kind=kind)
120
125
  if value is None:
121
126
  return expected_parameters_class()
122
127
  if not isinstance(value, expected_parameters_class) and isinstance(value, AttributeParameters):
123
- return expected_parameters_class(**value.model_dump())
128
+ return expected_parameters_class.convert_from(value)
129
+ if isinstance(value, dict):
130
+ return expected_parameters_class.convert_from_dict(source_data=value)
124
131
  return value
125
132
 
126
133
  @model_validator(mode="after")
@@ -168,7 +175,7 @@ class AttributeSchema(GeneratedAttributeSchema):
168
175
 
169
176
  def update_from_generic(self, other: AttributeSchema) -> None:
170
177
  fields_to_exclude = ("id", "order_weight", "branch", "inherited")
171
- for name in self.model_fields:
178
+ for name in self.__class__.model_fields:
172
179
  if name in fields_to_exclude:
173
180
  continue
174
181
  if getattr(self, name) != getattr(other, name):
@@ -238,19 +245,6 @@ class TextAttributeSchema(AttributeSchema):
238
245
  json_schema_extra={"update": UpdateSupport.VALIDATE_CONSTRAINT.value},
239
246
  )
240
247
 
241
- @model_validator(mode="after")
242
- def reconcile_parameters(self) -> Self:
243
- if self.regex != self.parameters.regex:
244
- final_regex = self.parameters.regex if self.parameters.regex is not None else self.regex
245
- self.regex = self.parameters.regex = final_regex
246
- if self.min_length != self.parameters.min_length:
247
- final_min_length = self.parameters.min_length if self.parameters.min_length is not None else self.min_length
248
- self.min_length = self.parameters.min_length = final_min_length
249
- if self.max_length != self.parameters.max_length:
250
- final_max_length = self.parameters.max_length if self.parameters.max_length is not None else self.max_length
251
- self.max_length = self.parameters.max_length = final_max_length
252
- return self
253
-
254
248
  def get_regex(self) -> str | None:
255
249
  return self.parameters.regex
256
250
 
@@ -263,6 +263,9 @@ class BaseNodeSchema(GeneratedBaseNodeSchema):
263
263
  ) -> AttributeSchema | RelationshipSchema | None: ...
264
264
 
265
265
  def get_field(self, name: str, raise_on_error: bool = True) -> AttributeSchema | RelationshipSchema | None:
266
+ if name in NODE_PROPERTY_ATTRIBUTES:
267
+ return self.get_attribute(name=name)
268
+
266
269
  if field := self.get_attribute_or_none(name=name):
267
270
  return field
268
271
 
@@ -1,4 +1,4 @@
1
- from typing import Any
1
+ from typing import Any, TypedDict
2
2
 
3
3
  from infrahub.actions.schema import (
4
4
  core_action,
@@ -93,7 +93,13 @@ from .template import core_object_component_template, core_object_template
93
93
  from .transform import core_transform, core_transform_jinja2, core_transform_python
94
94
  from .webhook import core_custom_webhook, core_standard_webhook, core_webhook
95
95
 
96
- core_models_mixed: dict[str, list] = {
96
+
97
+ class CoreModelsMixedType(TypedDict):
98
+ generics: list[GenericSchema]
99
+ nodes: list[NodeSchema]
100
+
101
+
102
+ core_models_mixed: CoreModelsMixedType = {
97
103
  "generics": [
98
104
  core_action,
99
105
  core_trigger_rule,
@@ -43,8 +43,8 @@ core_account_token = NodeSchema(
43
43
  documentation="/topics/auth",
44
44
  attributes=[
45
45
  Attr(name="name", kind="Text", optional=True),
46
- Attr(name="token", kind="Text", unique=True),
47
- Attr(name="expiration", kind="DateTime", optional=True),
46
+ Attr(name="token", kind="Text", description="The authentication token value", unique=True),
47
+ Attr(name="expiration", kind="DateTime", description="Date and time when the token expires", optional=True),
48
48
  ],
49
49
  relationships=[
50
50
  Rel(
@@ -68,13 +68,7 @@ core_password_credential = NodeSchema(
68
68
  inherit_from=[InfrahubKind.CREDENTIAL],
69
69
  attributes=[
70
70
  Attr(name="username", kind="Text", optional=True, branch=BranchSupportType.AGNOSTIC, order_weight=6000),
71
- Attr(
72
- name="password",
73
- kind="Password",
74
- optional=True,
75
- branch=BranchSupportType.AGNOSTIC,
76
- order_weight=7000,
77
- ),
71
+ Attr(name="password", kind="Password", optional=True, branch=BranchSupportType.AGNOSTIC, order_weight=7000),
78
72
  ],
79
73
  )
80
74
 
@@ -88,7 +82,12 @@ core_refresh_token = NodeSchema(
88
82
  generate_profile=False,
89
83
  branch=BranchSupportType.AGNOSTIC,
90
84
  attributes=[
91
- Attr(name="expiration", kind="DateTime", optional=False),
85
+ Attr(
86
+ name="expiration",
87
+ kind="DateTime",
88
+ description="Date and time when the refresh token expires",
89
+ optional=False,
90
+ ),
92
91
  ],
93
92
  relationships=[
94
93
  Rel(
@@ -144,6 +143,7 @@ core_generic_account = GenericSchema(
144
143
  Attr(
145
144
  name="account_type",
146
145
  kind="Text",
146
+ description="Type of account (user, script, etc.)",
147
147
  default_value=AccountType.USER.value,
148
148
  enum=AccountType.available_types(),
149
149
  ),
@@ -35,6 +35,7 @@ core_artifact_target = GenericSchema(
35
35
  core_artifact = NodeSchema(
36
36
  name="Artifact",
37
37
  namespace="Core",
38
+ description="A file generated by a transformation, associated with a specific object",
38
39
  label="Artifact",
39
40
  include_in_menu=False,
40
41
  icon="mdi:file-document-outline",
@@ -47,19 +48,17 @@ core_artifact = NodeSchema(
47
48
  documentation="/topics/artifact",
48
49
  attributes=[
49
50
  Attr(name="name", kind="Text"),
50
- Attr(
51
- name="status",
52
- kind="Text",
53
- enum=ArtifactStatus.available_types(),
54
- ),
51
+ Attr(name="status", kind="Text", enum=ArtifactStatus.available_types()),
55
52
  Attr(
56
53
  name="content_type",
57
54
  kind="Text",
55
+ description="MIME type of the artifact content",
58
56
  enum=ContentType.available_types(),
59
57
  ),
60
58
  Attr(
61
59
  name="checksum",
62
60
  kind="Text",
61
+ description="Hash checksum of the artifact content for integrity verification",
63
62
  optional=True,
64
63
  ),
65
64
  Attr(
@@ -71,6 +70,7 @@ core_artifact = NodeSchema(
71
70
  Attr(
72
71
  name="parameters",
73
72
  kind="JSON",
73
+ description="Input parameters used to generate this artifact",
74
74
  optional=True,
75
75
  ),
76
76
  ],
@@ -97,6 +97,7 @@ core_artifact = NodeSchema(
97
97
  core_artifact_definition = NodeSchema(
98
98
  name="ArtifactDefinition",
99
99
  namespace="Core",
100
+ description="Defines how artifacts are generated from a transformation for a group of targets",
100
101
  include_in_menu=False,
101
102
  icon="mdi:file-document-multiple-outline",
102
103
  label="Artifact Definition",
@@ -110,10 +111,15 @@ core_artifact_definition = NodeSchema(
110
111
  documentation="/topics/artifact",
111
112
  attributes=[
112
113
  Attr(name="name", kind="Text", unique=True),
113
- Attr(name="artifact_name", kind="Text"),
114
+ Attr(name="artifact_name", kind="Text", description="Name template for generated artifacts"),
114
115
  Attr(name="description", kind="Text", optional=True),
115
- Attr(name="parameters", kind="JSON"),
116
- Attr(name="content_type", kind="Text", enum=ContentType.available_types()),
116
+ Attr(name="parameters", kind="JSON", description="GraphQL query parameters for the transformation"),
117
+ Attr(
118
+ name="content_type",
119
+ kind="Text",
120
+ description="MIME type of the generated artifacts",
121
+ enum=ContentType.available_types(),
122
+ ),
117
123
  ],
118
124
  relationships=[
119
125
  Rel(
@@ -14,6 +14,7 @@ from ...relationship_schema import (
14
14
  core_check_definition = NodeSchema(
15
15
  name="CheckDefinition",
16
16
  namespace="Core",
17
+ description="Defines a user-defined check that validates data in a proposed change",
17
18
  include_in_menu=False,
18
19
  icon="mdi:check-all",
19
20
  label="Check Definition",
@@ -27,10 +28,15 @@ core_check_definition = NodeSchema(
27
28
  attributes=[
28
29
  Attr(name="name", kind="Text", unique=True),
29
30
  Attr(name="description", kind="Text", optional=True),
30
- Attr(name="file_path", kind="Text"),
31
- Attr(name="class_name", kind="Text"),
32
- Attr(name="timeout", kind="Number", default_value=60),
33
- Attr(name="parameters", kind="JSON", optional=True),
31
+ Attr(name="file_path", kind="Text", description="Path to the Python file containing the check class"),
32
+ Attr(name="class_name", kind="Text", description="Name of the Python class implementing the check"),
33
+ Attr(
34
+ name="timeout",
35
+ kind="Number",
36
+ description="Maximum execution time in seconds before the check times out",
37
+ default_value=60,
38
+ ),
39
+ Attr(name="parameters", kind="JSON", description="Additional parameters to pass to the check", optional=True),
34
40
  ],
35
41
  relationships=[
36
42
  Rel(
@@ -15,6 +15,7 @@ from ...relationship_schema import (
15
15
  core_generator_definition = NodeSchema(
16
16
  name="GeneratorDefinition",
17
17
  namespace="Core",
18
+ description="Defines a generator that creates or updates objects based on a GraphQL query",
18
19
  include_in_menu=False,
19
20
  icon="mdi:state-machine",
20
21
  label="Generator Definition",
@@ -29,12 +30,30 @@ core_generator_definition = NodeSchema(
29
30
  attributes=[
30
31
  Attr(name="name", kind="Text", unique=True),
31
32
  Attr(name="description", kind="Text", optional=True),
32
- Attr(name="parameters", kind="JSON"),
33
- Attr(name="file_path", kind="Text"),
34
- Attr(name="class_name", kind="Text"),
35
- Attr(name="convert_query_response", kind="Boolean", optional=True, default_value=False),
36
- Attr(name="execute_in_proposed_change", kind="Boolean", optional=True, default_value=True),
37
- Attr(name="execute_after_merge", kind="Boolean", optional=True, default_value=True),
33
+ Attr(name="parameters", kind="JSON", description="GraphQL query parameters for the generator"),
34
+ Attr(name="file_path", kind="Text", description="Path to the Python file containing the generator class"),
35
+ Attr(name="class_name", kind="Text", description="Name of the Python class implementing the generator"),
36
+ Attr(
37
+ name="convert_query_response",
38
+ kind="Boolean",
39
+ description="Whether to convert the GraphQL response to SDK objects",
40
+ optional=True,
41
+ default_value=False,
42
+ ),
43
+ Attr(
44
+ name="execute_in_proposed_change",
45
+ kind="Boolean",
46
+ description="Whether to run this generator in proposed changes",
47
+ optional=True,
48
+ default_value=True,
49
+ ),
50
+ Attr(
51
+ name="execute_after_merge",
52
+ kind="Boolean",
53
+ description="Whether to run this generator after a merge",
54
+ optional=True,
55
+ default_value=True,
56
+ ),
38
57
  ],
39
58
  relationships=[
40
59
  Rel(
@@ -67,6 +86,7 @@ core_generator_definition = NodeSchema(
67
86
  core_generator_instance = NodeSchema(
68
87
  name="GeneratorInstance",
69
88
  namespace="Core",
89
+ description="An instance of a generator execution for a specific object",
70
90
  label="Generator Instance",
71
91
  include_in_menu=False,
72
92
  icon="mdi:file-document-outline",
@@ -28,7 +28,7 @@ core_graphql_query = NodeSchema(
28
28
  attributes=[
29
29
  Attr(name="name", kind="Text", unique=True),
30
30
  Attr(name="description", kind="Text", optional=True),
31
- Attr(name="query", kind="TextArea"),
31
+ Attr(name="query", kind="TextArea", description="The GraphQL query string"),
32
32
  Attr(name="variables", kind="JSON", description="variables in use in the query", optional=True, read_only=True),
33
33
  Attr(
34
34
  name="operations",
@@ -31,7 +31,14 @@ core_group = GenericSchema(
31
31
  Attr(name="name", kind="Text", unique=True),
32
32
  Attr(name="label", kind="Text", optional=True),
33
33
  Attr(name="description", kind="Text", optional=True),
34
- Attr(name="group_type", kind="Text", enum=["default", "internal"], default_value="default", optional=False),
34
+ Attr(
35
+ name="group_type",
36
+ kind="Text",
37
+ description="Type of group (default or internal)",
38
+ enum=["default", "internal"],
39
+ default_value="default",
40
+ optional=False,
41
+ ),
35
42
  ],
36
43
  relationships=[
37
44
  Rel(
@@ -111,7 +118,7 @@ core_graphql_query_group = NodeSchema(
111
118
  inherit_from=[InfrahubKind.GENERICGROUP],
112
119
  generate_profile=False,
113
120
  attributes=[
114
- Attr(name="parameters", kind="JSON", optional=True),
121
+ Attr(name="parameters", kind="JSON", description="GraphQL query parameters for the group", optional=True),
115
122
  ],
116
123
  relationships=[
117
124
  Rel(
@@ -68,11 +68,18 @@ builtin_ip_prefix = GenericSchema(
68
68
  branch=BranchSupportType.AWARE,
69
69
  hierarchical=True,
70
70
  attributes=[
71
- Attr(name="prefix", kind="IPNetwork", branch=BranchSupportType.AWARE, order_weight=1000),
71
+ Attr(
72
+ name="prefix",
73
+ kind="IPNetwork",
74
+ description="The IP prefix in CIDR notation",
75
+ branch=BranchSupportType.AWARE,
76
+ order_weight=1000,
77
+ ),
72
78
  Attr(name="description", kind="Text", optional=True, branch=BranchSupportType.AWARE, order_weight=2000),
73
79
  Attr(
74
80
  name="member_type",
75
81
  kind="Dropdown",
82
+ description="Whether this prefix contains other prefixes or IP addresses",
76
83
  choices=[
77
84
  DropdownChoice(
78
85
  name="prefix",
@@ -97,13 +104,53 @@ builtin_ip_prefix = GenericSchema(
97
104
  order_weight=4000,
98
105
  description="All IP addresses within this prefix are considered usable",
99
106
  ),
100
- Attr(name="is_top_level", kind="Boolean", read_only=True, optional=True, allow_override=AllowOverrideType.NONE),
101
- Attr(name="utilization", kind="Number", read_only=True, optional=True, allow_override=AllowOverrideType.NONE),
102
- Attr(name="netmask", kind="Text", read_only=True, optional=True, allow_override=AllowOverrideType.NONE),
103
- Attr(name="hostmask", kind="Text", read_only=True, optional=True, allow_override=AllowOverrideType.NONE),
104
- Attr(name="network_address", kind="Text", read_only=True, optional=True, allow_override=AllowOverrideType.NONE),
105
107
  Attr(
106
- name="broadcast_address", kind="Text", read_only=True, optional=True, allow_override=AllowOverrideType.NONE
108
+ name="is_top_level",
109
+ kind="Boolean",
110
+ description="Whether this prefix has no parent prefix",
111
+ read_only=True,
112
+ optional=True,
113
+ allow_override=AllowOverrideType.NONE,
114
+ ),
115
+ Attr(
116
+ name="utilization",
117
+ kind="Number",
118
+ description="Percentage of the prefix that is allocated",
119
+ read_only=True,
120
+ optional=True,
121
+ allow_override=AllowOverrideType.NONE,
122
+ ),
123
+ Attr(
124
+ name="netmask",
125
+ kind="Text",
126
+ description="Subnet mask in dotted decimal notation",
127
+ read_only=True,
128
+ optional=True,
129
+ allow_override=AllowOverrideType.NONE,
130
+ ),
131
+ Attr(
132
+ name="hostmask",
133
+ kind="Text",
134
+ description="Wildcard mask in dotted decimal notation",
135
+ read_only=True,
136
+ optional=True,
137
+ allow_override=AllowOverrideType.NONE,
138
+ ),
139
+ Attr(
140
+ name="network_address",
141
+ kind="Text",
142
+ description="Network address of the prefix",
143
+ read_only=True,
144
+ optional=True,
145
+ allow_override=AllowOverrideType.NONE,
146
+ ),
147
+ Attr(
148
+ name="broadcast_address",
149
+ kind="Text",
150
+ description="Broadcast address of the prefix",
151
+ read_only=True,
152
+ optional=True,
153
+ allow_override=AllowOverrideType.NONE,
107
154
  ),
108
155
  ],
109
156
  relationships=[
@@ -150,7 +197,13 @@ builtin_ip_address = GenericSchema(
150
197
  icon="mdi:ip-outline",
151
198
  branch=BranchSupportType.AWARE,
152
199
  attributes=[
153
- Attr(name="address", kind="IPHost", branch=BranchSupportType.AWARE, order_weight=1000),
200
+ Attr(
201
+ name="address",
202
+ kind="IPHost",
203
+ description="The IP address with prefix length",
204
+ branch=BranchSupportType.AWARE,
205
+ order_weight=1000,
206
+ ),
154
207
  Attr(name="description", kind="Text", optional=True, branch=BranchSupportType.AWARE, order_weight=2000),
155
208
  ],
156
209
  relationships=[
@@ -186,7 +239,15 @@ internal_ipam_ip_range_available = NodeSchema(
186
239
  branch=BranchSupportType.AWARE,
187
240
  inherit_from=[InfrahubKind.IPADDRESS],
188
241
  generate_profile=False,
189
- attributes=[Attr(name="last_address", kind="IPHost", branch=BranchSupportType.AWARE, order_weight=2000)],
242
+ attributes=[
243
+ Attr(
244
+ name="last_address",
245
+ kind="IPHost",
246
+ description="Last IP address in the available range",
247
+ branch=BranchSupportType.AWARE,
248
+ order_weight=2000,
249
+ )
250
+ ],
190
251
  )
191
252
 
192
253
  internal_ipam_ip_prefix_available = NodeSchema(
@@ -215,5 +276,14 @@ core_ipam_namespace = NodeSchema(
215
276
  icon="mdi:format-list-group",
216
277
  branch=BranchSupportType.AWARE,
217
278
  inherit_from=[InfrahubKind.IPNAMESPACE],
218
- attributes=[Attr(name="default", kind="Boolean", optional=True, read_only=True, order_weight=9000)],
279
+ attributes=[
280
+ Attr(
281
+ name="default",
282
+ kind="Boolean",
283
+ description="Whether this is the default IPAM namespace",
284
+ optional=True,
285
+ read_only=True,
286
+ order_weight=9000,
287
+ )
288
+ ],
219
289
  )
@@ -17,19 +17,53 @@ generic_menu_item = GenericSchema(
17
17
  display_labels=["label__value"],
18
18
  generate_profile=False,
19
19
  attributes=[
20
- Attr(name="namespace", kind="Text", regex=NAMESPACE_REGEX, order_weight=1000),
20
+ Attr(
21
+ name="namespace",
22
+ kind="Text",
23
+ description="Namespace for the menu item",
24
+ regex=NAMESPACE_REGEX,
25
+ order_weight=1000,
26
+ ),
21
27
  Attr(name="name", kind="Text", order_weight=1000),
22
28
  Attr(name="label", kind="Text", optional=True, order_weight=2000),
23
- Attr(name="kind", kind="Text", optional=True, order_weight=2500),
24
- Attr(name="path", kind="Text", optional=True, order_weight=2500),
29
+ Attr(
30
+ name="kind",
31
+ kind="Text",
32
+ description="Kind of object this menu item links to",
33
+ optional=True,
34
+ order_weight=2500,
35
+ ),
36
+ Attr(name="path", kind="Text", description="URL path for the menu item", optional=True, order_weight=2500),
25
37
  Attr(name="description", kind="Text", optional=True, order_weight=3000),
26
- Attr(name="icon", kind="Text", optional=True, order_weight=4000),
27
- Attr(name="protected", kind="Boolean", default_value=False, read_only=True, order_weight=5000),
28
- Attr(name="order_weight", kind="Number", default_value=2000, order_weight=6000),
29
- Attr(name="required_permissions", kind="List", optional=True, order_weight=7000),
38
+ Attr(
39
+ name="icon", kind="Text", description="Icon identifier for the menu item", optional=True, order_weight=4000
40
+ ),
41
+ Attr(
42
+ name="protected",
43
+ kind="Boolean",
44
+ description="Whether the menu item is protected from modification",
45
+ default_value=False,
46
+ read_only=True,
47
+ order_weight=5000,
48
+ ),
49
+ Attr(
50
+ name="order_weight",
51
+ kind="Number",
52
+ description="Ordering weight for menu item placement",
53
+ default_value=2000,
54
+ order_weight=6000,
55
+ ),
56
+ Attr(
57
+ name="required_permissions",
58
+ kind="List",
59
+ description="List of permissions required to view this menu item",
60
+ optional=True,
61
+ order_weight=7000,
62
+ ),
30
63
  Attr(
31
64
  name="section",
32
65
  kind="Text",
66
+ description="Section where the menu item appears",
33
67
  enum=["object", "internal"],
34
68
  default_value="object",
35
69
  order_weight=8000,
@@ -27,7 +27,14 @@ core_base_permission = GenericSchema(
27
27
  generate_profile=False,
28
28
  attributes=[
29
29
  Attr(name="description", kind="Text", optional=True),
30
- Attr(name="identifier", kind="Text", read_only=True, optional=True, allow_override=AllowOverrideType.NONE),
30
+ Attr(
31
+ name="identifier",
32
+ kind="Text",
33
+ description="Identifier for the permission",
34
+ read_only=True,
35
+ optional=True,
36
+ allow_override=AllowOverrideType.NONE,
37
+ ),
31
38
  ],
32
39
  relationships=[
33
40
  Rel(
@@ -54,11 +61,17 @@ core_object_permission = NodeSchema(
54
61
  generate_profile=False,
55
62
  inherit_from=[InfrahubKind.BASEPERMISSION],
56
63
  attributes=[
57
- Attr(name="namespace", kind="Text", order_weight=2000),
64
+ Attr(
65
+ name="namespace",
66
+ kind="Text",
67
+ description="Namespace of the object type this permission applies to",
68
+ order_weight=2000,
69
+ ),
58
70
  Attr(name="name", kind="Text", order_weight=3000),
59
71
  Attr(
60
72
  name="action",
61
73
  kind="Text",
74
+ description="The action this permission grants or denies",
62
75
  enum=PermissionAction.available_types(),
63
76
  default_value=PermissionAction.ANY.value,
64
77
  order_weight=4000,
@@ -91,6 +104,7 @@ core_global_permission = NodeSchema(
91
104
  Attr(
92
105
  name="action",
93
106
  kind="Dropdown",
107
+ description="The global action this permission grants or denies",
94
108
  choices=[DropdownChoice(name=permission.value) for permission in GlobalPermissions],
95
109
  order_weight=2000,
96
110
  ),
@@ -12,7 +12,21 @@ core_profile_schema_definition = GenericSchema(
12
12
  default_filter="profile_name__value",
13
13
  uniqueness_constraints=[["profile_name__value"]],
14
14
  attributes=[
15
- Attr(name="profile_name", kind="Text", min_length=3, max_length=32, unique=True, optional=False),
16
- Attr(name="profile_priority", kind="Number", default_value=1000, optional=True),
15
+ Attr(
16
+ name="profile_name",
17
+ kind="Text",
18
+ description="Unique name identifier for the profile",
19
+ min_length=3,
20
+ max_length=32,
21
+ unique=True,
22
+ optional=False,
23
+ ),
24
+ Attr(
25
+ name="profile_priority",
26
+ kind="Number",
27
+ description="Priority level for profile application (lower numbers have higher priority)",
28
+ default_value=1000,
29
+ optional=True,
30
+ ),
17
31
  ],
18
32
  )
@@ -29,18 +29,38 @@ core_proposed_change = NodeSchema(
29
29
  attributes=[
30
30
  Attr(name="name", kind="Text", optional=False),
31
31
  Attr(name="description", kind="TextArea", optional=True),
32
- Attr(name="source_branch", kind="Text", optional=False),
33
- Attr(name="destination_branch", kind="Text", optional=False),
32
+ Attr(
33
+ name="source_branch", kind="Text", description="Name of the branch containing the changes", optional=False
34
+ ),
35
+ Attr(
36
+ name="destination_branch",
37
+ kind="Text",
38
+ description="Name of the branch to merge changes into",
39
+ optional=False,
40
+ ),
34
41
  Attr(
35
42
  name="state",
36
43
  kind="Text",
44
+ description="Current state of the proposed change",
37
45
  enum=ProposedChangeState.available_types(),
38
46
  default_value=ProposedChangeState.OPEN.value,
39
47
  optional=True,
40
48
  ),
41
- Attr(name="is_draft", kind="Boolean", optional=False, default_value=False),
49
+ Attr(
50
+ name="is_draft",
51
+ kind="Boolean",
52
+ description="Whether the proposed change is still a draft",
53
+ optional=False,
54
+ default_value=False,
55
+ ),
42
56
  # Ideally we should support some "runtime-attribute" that could not even be stored in the database.
43
- Attr(name="total_comments", kind="Number", optional=True, read_only=True),
57
+ Attr(
58
+ name="total_comments",
59
+ kind="Number",
60
+ description="Total number of comments on this proposed change",
61
+ optional=True,
62
+ read_only=True,
63
+ ),
44
64
  ],
45
65
  relationships=[
46
66
  Rel(