infrahub-server 1.2.12__py3-none-any.whl → 1.3.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 (205) hide show
  1. infrahub/actions/constants.py +130 -0
  2. infrahub/actions/gather.py +114 -0
  3. infrahub/actions/models.py +243 -0
  4. infrahub/actions/parsers.py +104 -0
  5. infrahub/actions/schema.py +393 -0
  6. infrahub/actions/tasks.py +119 -0
  7. infrahub/actions/triggers.py +21 -0
  8. infrahub/branch/__init__.py +0 -0
  9. infrahub/branch/tasks.py +29 -0
  10. infrahub/branch/triggers.py +22 -0
  11. infrahub/cli/db.py +3 -4
  12. infrahub/computed_attribute/gather.py +3 -1
  13. infrahub/computed_attribute/tasks.py +23 -29
  14. infrahub/core/account.py +24 -47
  15. infrahub/core/attribute.py +13 -15
  16. infrahub/core/constants/__init__.py +10 -0
  17. infrahub/core/constants/infrahubkind.py +9 -0
  18. infrahub/core/constraint/node/runner.py +3 -1
  19. infrahub/core/convert_object_type/__init__.py +0 -0
  20. infrahub/core/convert_object_type/conversion.py +124 -0
  21. infrahub/core/convert_object_type/schema_mapping.py +56 -0
  22. infrahub/core/diff/coordinator.py +8 -1
  23. infrahub/core/diff/query/all_conflicts.py +1 -5
  24. infrahub/core/diff/query/artifact.py +10 -20
  25. infrahub/core/diff/query/delete_query.py +8 -4
  26. infrahub/core/diff/query/diff_get.py +3 -6
  27. infrahub/core/diff/query/field_specifiers.py +1 -1
  28. infrahub/core/diff/query/field_summary.py +2 -4
  29. infrahub/core/diff/query/merge.py +72 -125
  30. infrahub/core/diff/query/save.py +28 -43
  31. infrahub/core/diff/query/summary_counts_enricher.py +34 -54
  32. infrahub/core/diff/query/time_range_query.py +0 -1
  33. infrahub/core/diff/repository/repository.py +4 -0
  34. infrahub/core/manager.py +14 -11
  35. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
  36. infrahub/core/migrations/graph/m012_convert_account_generic.py +1 -1
  37. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -6
  38. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -2
  39. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -2
  40. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +11 -22
  41. infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -6
  42. infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +1 -2
  43. infrahub/core/migrations/graph/m023_deduplicate_cardinality_one_relationships.py +2 -2
  44. infrahub/core/migrations/graph/m024_missing_hierarchy_backfill.py +1 -2
  45. infrahub/core/migrations/graph/m028_delete_diffs.py +1 -2
  46. infrahub/core/migrations/graph/m029_duplicates_cleanup.py +30 -48
  47. infrahub/core/migrations/graph/m030_illegal_edges.py +1 -2
  48. infrahub/core/migrations/query/attribute_add.py +1 -2
  49. infrahub/core/migrations/query/attribute_rename.py +6 -11
  50. infrahub/core/migrations/query/delete_element_in_schema.py +19 -17
  51. infrahub/core/migrations/query/node_duplicate.py +19 -21
  52. infrahub/core/migrations/query/relationship_duplicate.py +19 -18
  53. infrahub/core/migrations/schema/node_attribute_remove.py +4 -8
  54. infrahub/core/migrations/schema/node_remove.py +19 -20
  55. infrahub/core/models.py +29 -2
  56. infrahub/core/node/__init__.py +131 -28
  57. infrahub/core/node/base.py +1 -1
  58. infrahub/core/node/create.py +211 -0
  59. infrahub/core/node/resource_manager/number_pool.py +31 -5
  60. infrahub/core/node/standard.py +6 -1
  61. infrahub/core/path.py +15 -1
  62. infrahub/core/protocols.py +57 -0
  63. infrahub/core/protocols_base.py +3 -0
  64. infrahub/core/query/__init__.py +2 -2
  65. infrahub/core/query/delete.py +3 -3
  66. infrahub/core/query/diff.py +19 -32
  67. infrahub/core/query/ipam.py +10 -20
  68. infrahub/core/query/node.py +29 -47
  69. infrahub/core/query/relationship.py +55 -34
  70. infrahub/core/query/resource_manager.py +1 -2
  71. infrahub/core/query/standard_node.py +19 -5
  72. infrahub/core/query/subquery.py +2 -4
  73. infrahub/core/relationship/constraints/count.py +10 -9
  74. infrahub/core/relationship/constraints/interface.py +2 -1
  75. infrahub/core/relationship/constraints/peer_kind.py +2 -1
  76. infrahub/core/relationship/constraints/peer_parent.py +56 -0
  77. infrahub/core/relationship/constraints/peer_relatives.py +72 -0
  78. infrahub/core/relationship/constraints/profiles_kind.py +1 -1
  79. infrahub/core/relationship/model.py +4 -1
  80. infrahub/core/schema/__init__.py +2 -1
  81. infrahub/core/schema/attribute_parameters.py +160 -0
  82. infrahub/core/schema/attribute_schema.py +130 -7
  83. infrahub/core/schema/basenode_schema.py +27 -3
  84. infrahub/core/schema/definitions/core/__init__.py +29 -1
  85. infrahub/core/schema/definitions/core/group.py +45 -0
  86. infrahub/core/schema/definitions/core/resource_pool.py +9 -0
  87. infrahub/core/schema/definitions/internal.py +43 -5
  88. infrahub/core/schema/generated/attribute_schema.py +16 -3
  89. infrahub/core/schema/generated/relationship_schema.py +11 -1
  90. infrahub/core/schema/manager.py +7 -2
  91. infrahub/core/schema/schema_branch.py +104 -9
  92. infrahub/core/validators/__init__.py +15 -2
  93. infrahub/core/validators/attribute/choices.py +1 -3
  94. infrahub/core/validators/attribute/enum.py +1 -3
  95. infrahub/core/validators/attribute/kind.py +1 -3
  96. infrahub/core/validators/attribute/length.py +13 -7
  97. infrahub/core/validators/attribute/min_max.py +118 -0
  98. infrahub/core/validators/attribute/number_pool.py +106 -0
  99. infrahub/core/validators/attribute/optional.py +1 -4
  100. infrahub/core/validators/attribute/regex.py +5 -6
  101. infrahub/core/validators/attribute/unique.py +1 -3
  102. infrahub/core/validators/determiner.py +18 -2
  103. infrahub/core/validators/enum.py +12 -0
  104. infrahub/core/validators/node/hierarchy.py +3 -6
  105. infrahub/core/validators/query.py +1 -3
  106. infrahub/core/validators/relationship/count.py +6 -12
  107. infrahub/core/validators/relationship/optional.py +2 -4
  108. infrahub/core/validators/relationship/peer.py +177 -12
  109. infrahub/core/validators/tasks.py +1 -1
  110. infrahub/core/validators/uniqueness/query.py +5 -9
  111. infrahub/database/__init__.py +12 -4
  112. infrahub/database/validation.py +1 -2
  113. infrahub/dependencies/builder/constraint/grouped/node_runner.py +4 -0
  114. infrahub/dependencies/builder/constraint/relationship_manager/peer_parent.py +8 -0
  115. infrahub/dependencies/builder/constraint/relationship_manager/peer_relatives.py +8 -0
  116. infrahub/dependencies/builder/constraint/schema/aggregated.py +2 -0
  117. infrahub/dependencies/builder/constraint/schema/relationship_peer.py +8 -0
  118. infrahub/dependencies/builder/diff/deserializer.py +1 -1
  119. infrahub/dependencies/registry.py +4 -0
  120. infrahub/events/group_action.py +1 -0
  121. infrahub/events/models.py +1 -1
  122. infrahub/git/base.py +5 -3
  123. infrahub/git/integrator.py +96 -5
  124. infrahub/git/tasks.py +1 -0
  125. infrahub/graphql/analyzer.py +139 -18
  126. infrahub/graphql/manager.py +4 -0
  127. infrahub/graphql/mutations/action.py +164 -0
  128. infrahub/graphql/mutations/convert_object_type.py +71 -0
  129. infrahub/graphql/mutations/main.py +24 -175
  130. infrahub/graphql/mutations/proposed_change.py +20 -17
  131. infrahub/graphql/mutations/relationship.py +32 -0
  132. infrahub/graphql/mutations/resource_manager.py +63 -7
  133. infrahub/graphql/queries/convert_object_type_mapping.py +34 -0
  134. infrahub/graphql/queries/resource_manager.py +7 -1
  135. infrahub/graphql/resolvers/many_relationship.py +1 -1
  136. infrahub/graphql/resolvers/resolver.py +2 -2
  137. infrahub/graphql/resolvers/single_relationship.py +1 -1
  138. infrahub/graphql/schema.py +6 -0
  139. infrahub/menu/menu.py +34 -2
  140. infrahub/message_bus/messages/__init__.py +0 -10
  141. infrahub/message_bus/operations/__init__.py +0 -8
  142. infrahub/message_bus/operations/refresh/registry.py +3 -6
  143. infrahub/patch/queries/delete_duplicated_edges.py +10 -15
  144. infrahub/pools/models.py +14 -0
  145. infrahub/pools/number.py +5 -3
  146. infrahub/pools/registration.py +22 -0
  147. infrahub/pools/tasks.py +126 -0
  148. infrahub/prefect_server/models.py +1 -19
  149. infrahub/proposed_change/models.py +68 -3
  150. infrahub/proposed_change/tasks.py +911 -34
  151. infrahub/schema/__init__.py +0 -0
  152. infrahub/schema/tasks.py +27 -0
  153. infrahub/schema/triggers.py +23 -0
  154. infrahub/task_manager/models.py +10 -6
  155. infrahub/trigger/catalogue.py +6 -0
  156. infrahub/trigger/models.py +23 -6
  157. infrahub/trigger/setup.py +26 -2
  158. infrahub/trigger/tasks.py +4 -2
  159. infrahub/types.py +6 -0
  160. infrahub/webhook/tasks.py +4 -8
  161. infrahub/workflows/catalogue.py +103 -1
  162. infrahub_sdk/client.py +43 -10
  163. infrahub_sdk/ctl/generator.py +4 -4
  164. infrahub_sdk/ctl/repository.py +1 -1
  165. infrahub_sdk/node/__init__.py +39 -0
  166. infrahub_sdk/node/attribute.py +122 -0
  167. infrahub_sdk/node/constants.py +21 -0
  168. infrahub_sdk/{node.py → node/node.py} +158 -803
  169. infrahub_sdk/node/parsers.py +15 -0
  170. infrahub_sdk/node/property.py +24 -0
  171. infrahub_sdk/node/related_node.py +266 -0
  172. infrahub_sdk/node/relationship.py +302 -0
  173. infrahub_sdk/protocols.py +112 -0
  174. infrahub_sdk/protocols_base.py +34 -2
  175. infrahub_sdk/pytest_plugin/items/python_transform.py +2 -1
  176. infrahub_sdk/query_groups.py +17 -5
  177. infrahub_sdk/schema/main.py +1 -0
  178. infrahub_sdk/schema/repository.py +16 -0
  179. infrahub_sdk/spec/object.py +1 -1
  180. infrahub_sdk/store.py +1 -1
  181. infrahub_sdk/testing/schemas/car_person.py +1 -0
  182. infrahub_sdk/utils.py +7 -20
  183. infrahub_sdk/yaml.py +6 -5
  184. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/METADATA +3 -3
  185. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/RECORD +192 -166
  186. infrahub_testcontainers/container.py +0 -1
  187. infrahub_testcontainers/docker-compose.test.yml +1 -1
  188. infrahub_testcontainers/helpers.py +8 -2
  189. infrahub/message_bus/messages/check_generator_run.py +0 -26
  190. infrahub/message_bus/messages/finalize_validator_execution.py +0 -15
  191. infrahub/message_bus/messages/proposed_change/base_with_diff.py +0 -16
  192. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +0 -11
  193. infrahub/message_bus/messages/request_generatordefinition_check.py +0 -20
  194. infrahub/message_bus/messages/request_proposedchange_pipeline.py +0 -23
  195. infrahub/message_bus/operations/check/__init__.py +0 -3
  196. infrahub/message_bus/operations/check/generator.py +0 -156
  197. infrahub/message_bus/operations/finalize/__init__.py +0 -3
  198. infrahub/message_bus/operations/finalize/validator.py +0 -133
  199. infrahub/message_bus/operations/requests/__init__.py +0 -9
  200. infrahub/message_bus/operations/requests/generator_definition.py +0 -140
  201. infrahub/message_bus/operations/requests/proposed_change.py +0 -629
  202. /infrahub/{message_bus/messages/proposed_change → actions}/__init__.py +0 -0
  203. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/LICENSE.txt +0 -0
  204. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/WHEEL +0 -0
  205. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/entry_points.txt +0 -0
infrahub_sdk/protocols.py CHANGED
@@ -68,6 +68,12 @@ class BuiltinIPPrefix(CoreNode):
68
68
  children: RelationshipManager
69
69
 
70
70
 
71
+ class CoreAction(CoreNode):
72
+ name: String
73
+ description: StringOptional
74
+ triggers: RelationshipManager
75
+
76
+
71
77
  class CoreArtifactTarget(CoreNode):
72
78
  artifacts: RelationshipManager
73
79
 
@@ -154,6 +160,10 @@ class CoreMenu(CoreNode):
154
160
  children: RelationshipManager
155
161
 
156
162
 
163
+ class CoreNodeTriggerMatch(CoreNode):
164
+ trigger: RelatedNode
165
+
166
+
157
167
  class CoreObjectComponentTemplate(CoreNode):
158
168
  template_name: String
159
169
 
@@ -195,6 +205,14 @@ class CoreTransformation(CoreNode):
195
205
  tags: RelationshipManager
196
206
 
197
207
 
208
+ class CoreTriggerRule(CoreNode):
209
+ name: String
210
+ description: StringOptional
211
+ active: Boolean
212
+ branch_scope: Dropdown
213
+ action: RelatedNode
214
+
215
+
198
216
  class CoreValidator(CoreNode):
199
217
  label: StringOptional
200
218
  state: Enum
@@ -328,6 +346,10 @@ class CoreFileThread(CoreThread):
328
346
  repository: RelatedNode
329
347
 
330
348
 
349
+ class CoreGeneratorAction(CoreAction):
350
+ generator: RelatedNode
351
+
352
+
331
353
  class CoreGeneratorCheck(CoreCheck):
332
354
  instance: String
333
355
 
@@ -382,6 +404,16 @@ class CoreGraphQLQueryGroup(CoreGroup):
382
404
  query: RelatedNode
383
405
 
384
406
 
407
+ class CoreGroupAction(CoreAction):
408
+ add_members: Boolean
409
+ group: RelatedNode
410
+
411
+
412
+ class CoreGroupTriggerRule(CoreTriggerRule):
413
+ members_added: Boolean
414
+ group: RelatedNode
415
+
416
+
385
417
  class CoreIPAddressPool(CoreResourcePool, LineageSource):
386
418
  default_address_type: String
387
419
  default_prefix_length: IntegerOptional
@@ -401,6 +433,25 @@ class CoreMenuItem(CoreMenu):
401
433
  pass
402
434
 
403
435
 
436
+ class CoreNodeTriggerAttributeMatch(CoreNodeTriggerMatch):
437
+ attribute_name: String
438
+ value: StringOptional
439
+ value_previous: StringOptional
440
+ value_match: Dropdown
441
+
442
+
443
+ class CoreNodeTriggerRelationshipMatch(CoreNodeTriggerMatch):
444
+ relationship_name: String
445
+ added: Boolean
446
+ peer: StringOptional
447
+
448
+
449
+ class CoreNodeTriggerRule(CoreTriggerRule):
450
+ node_kind: String
451
+ mutation_action: Enum
452
+ matches: RelationshipManager
453
+
454
+
404
455
  class CoreNumberPool(CoreResourcePool, LineageSource):
405
456
  node: String
406
457
  node_attribute: String
@@ -448,6 +499,11 @@ class CoreRepository(LineageOwner, LineageSource, CoreGenericRepository, CoreTas
448
499
  commit: StringOptional
449
500
 
450
501
 
502
+ class CoreRepositoryGroup(CoreGroup):
503
+ content: Dropdown
504
+ repository: RelatedNode
505
+
506
+
451
507
  class CoreRepositoryValidator(CoreValidator):
452
508
  repository: RelatedNode
453
509
 
@@ -545,6 +601,12 @@ class BuiltinIPPrefixSync(CoreNodeSync):
545
601
  children: RelationshipManagerSync
546
602
 
547
603
 
604
+ class CoreActionSync(CoreNodeSync):
605
+ name: String
606
+ description: StringOptional
607
+ triggers: RelationshipManagerSync
608
+
609
+
548
610
  class CoreArtifactTargetSync(CoreNodeSync):
549
611
  artifacts: RelationshipManagerSync
550
612
 
@@ -631,6 +693,10 @@ class CoreMenuSync(CoreNodeSync):
631
693
  children: RelationshipManagerSync
632
694
 
633
695
 
696
+ class CoreNodeTriggerMatchSync(CoreNodeSync):
697
+ trigger: RelatedNodeSync
698
+
699
+
634
700
  class CoreObjectComponentTemplateSync(CoreNodeSync):
635
701
  template_name: String
636
702
 
@@ -672,6 +738,14 @@ class CoreTransformationSync(CoreNodeSync):
672
738
  tags: RelationshipManagerSync
673
739
 
674
740
 
741
+ class CoreTriggerRuleSync(CoreNodeSync):
742
+ name: String
743
+ description: StringOptional
744
+ active: Boolean
745
+ branch_scope: Dropdown
746
+ action: RelatedNodeSync
747
+
748
+
675
749
  class CoreValidatorSync(CoreNodeSync):
676
750
  label: StringOptional
677
751
  state: Enum
@@ -805,6 +879,10 @@ class CoreFileThreadSync(CoreThreadSync):
805
879
  repository: RelatedNodeSync
806
880
 
807
881
 
882
+ class CoreGeneratorActionSync(CoreActionSync):
883
+ generator: RelatedNodeSync
884
+
885
+
808
886
  class CoreGeneratorCheckSync(CoreCheckSync):
809
887
  instance: String
810
888
 
@@ -859,6 +937,16 @@ class CoreGraphQLQueryGroupSync(CoreGroupSync):
859
937
  query: RelatedNodeSync
860
938
 
861
939
 
940
+ class CoreGroupActionSync(CoreActionSync):
941
+ add_members: Boolean
942
+ group: RelatedNodeSync
943
+
944
+
945
+ class CoreGroupTriggerRuleSync(CoreTriggerRuleSync):
946
+ members_added: Boolean
947
+ group: RelatedNodeSync
948
+
949
+
862
950
  class CoreIPAddressPoolSync(CoreResourcePoolSync, LineageSourceSync):
863
951
  default_address_type: String
864
952
  default_prefix_length: IntegerOptional
@@ -878,6 +966,25 @@ class CoreMenuItemSync(CoreMenuSync):
878
966
  pass
879
967
 
880
968
 
969
+ class CoreNodeTriggerAttributeMatchSync(CoreNodeTriggerMatchSync):
970
+ attribute_name: String
971
+ value: StringOptional
972
+ value_previous: StringOptional
973
+ value_match: Dropdown
974
+
975
+
976
+ class CoreNodeTriggerRelationshipMatchSync(CoreNodeTriggerMatchSync):
977
+ relationship_name: String
978
+ added: Boolean
979
+ peer: StringOptional
980
+
981
+
982
+ class CoreNodeTriggerRuleSync(CoreTriggerRuleSync):
983
+ node_kind: String
984
+ mutation_action: Enum
985
+ matches: RelationshipManagerSync
986
+
987
+
881
988
  class CoreNumberPoolSync(CoreResourcePoolSync, LineageSourceSync):
882
989
  node: String
883
990
  node_attribute: String
@@ -925,6 +1032,11 @@ class CoreRepositorySync(LineageOwnerSync, LineageSourceSync, CoreGenericReposit
925
1032
  commit: StringOptional
926
1033
 
927
1034
 
1035
+ class CoreRepositoryGroupSync(CoreGroupSync):
1036
+ content: Dropdown
1037
+ repository: RelatedNodeSync
1038
+
1039
+
928
1040
  class CoreRepositoryValidatorSync(CoreValidatorSync):
929
1041
  repository: RelatedNodeSync
930
1042
 
@@ -10,11 +10,42 @@ if TYPE_CHECKING:
10
10
 
11
11
 
12
12
  @runtime_checkable
13
- class RelatedNode(Protocol): ...
13
+ class RelatedNodeBase(Protocol):
14
+ @property
15
+ def id(self) -> str | None: ...
16
+
17
+ @property
18
+ def hfid(self) -> list[Any] | None: ...
19
+
20
+ @property
21
+ def hfid_str(self) -> str | None: ...
22
+
23
+ @property
24
+ def is_resource_pool(self) -> bool: ...
25
+
26
+ @property
27
+ def initialized(self) -> bool: ...
28
+
29
+ @property
30
+ def display_label(self) -> str | None: ...
31
+
32
+ @property
33
+ def typename(self) -> str | None: ...
34
+
35
+ def _generate_input_data(self, allocate_from_pool: bool = False) -> dict[str, Any]: ...
36
+
37
+ def _generate_mutation_query(self) -> dict[str, Any]: ...
38
+
39
+ @classmethod
40
+ def _generate_query_data(cls, peer_data: dict[str, Any] | None = None, property: bool = False) -> dict: ...
41
+
42
+
43
+ @runtime_checkable
44
+ class RelatedNode(RelatedNodeBase, Protocol): ...
14
45
 
15
46
 
16
47
  @runtime_checkable
17
- class RelatedNodeSync(Protocol): ...
48
+ class RelatedNodeSync(RelatedNodeBase, Protocol): ...
18
49
 
19
50
 
20
51
  @runtime_checkable
@@ -147,6 +178,7 @@ class CoreNodeBase(Protocol):
147
178
  _internal_id: str
148
179
  id: str # NOTE this is incorrect, should be str | None
149
180
  display_label: str | None
181
+ typename: str | None
150
182
 
151
183
  @property
152
184
  def hfid(self) -> list[str] | None: ...
@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Any
7
7
  import ujson
8
8
  from httpx import HTTPStatusError
9
9
 
10
+ from ...node import InfrahubNode
10
11
  from ..exceptions import OutputMatchError, PythonTransformDefinitionError
11
12
  from ..models import InfrahubTestExpectedResult
12
13
  from .base import InfrahubItem
@@ -41,7 +42,7 @@ class InfrahubPythonTransformItem(InfrahubItem):
41
42
  )
42
43
  client = self.session.infrahub_client # type: ignore[attr-defined]
43
44
  # TODO: Look into seeing how a transform class may use the branch, but set as a empty string for the time being to keep current behaviour
44
- self.transform_instance = transform_class(branch="", client=client)
45
+ self.transform_instance = transform_class(branch="", client=client, infrahub_node=InfrahubNode)
45
46
 
46
47
  def run_transform(self, variables: dict[str, Any]) -> Any:
47
48
  self.instantiate_transform()
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING
3
+ from collections.abc import Sequence
4
+ from typing import TYPE_CHECKING, Any
4
5
 
5
6
  from .constants import InfrahubClientMode
6
7
  from .exceptions import NodeNotFoundError
@@ -19,12 +20,13 @@ class InfrahubGroupContextBase:
19
20
  self.related_node_ids: list[str] = []
20
21
  self.related_group_ids: list[str] = []
21
22
  self.unused_member_ids: list[str] | None = None
22
- self.previous_members: list[RelatedNodeBase] | None = None
23
+ self.previous_members: Sequence[RelatedNodeBase] | None = None
23
24
  self.previous_children: list[RelatedNodeBase] | None = None
24
25
  self.identifier: str | None = None
25
26
  self.params: dict[str, str] = {}
26
27
  self.delete_unused_nodes: bool = False
27
28
  self.group_type: str = "CoreStandardGroup"
29
+ self.group_params: dict[str, Any] = {}
28
30
 
29
31
  def set_properties(
30
32
  self,
@@ -32,6 +34,8 @@ class InfrahubGroupContextBase:
32
34
  params: dict[str, str] | None = None,
33
35
  delete_unused_nodes: bool = False,
34
36
  group_type: str | None = None,
37
+ group_params: dict[str, Any] | None = None,
38
+ branch: str | None = None,
35
39
  ) -> None:
36
40
  """Setter method to set the values of identifier and params.
37
41
 
@@ -43,6 +47,8 @@ class InfrahubGroupContextBase:
43
47
  self.params = params or {}
44
48
  self.delete_unused_nodes = delete_unused_nodes
45
49
  self.group_type = group_type or self.group_type
50
+ self.group_params = group_params or {}
51
+ self.branch = branch
46
52
 
47
53
  def _get_params_as_str(self) -> str:
48
54
  """Convert the params in dict format, into a string"""
@@ -87,14 +93,16 @@ class InfrahubGroupContext(InfrahubGroupContextBase):
87
93
  async def get_group(self, store_peers: bool = False) -> InfrahubNode | None:
88
94
  group_name = self._generate_group_name()
89
95
  try:
90
- group = await self.client.get(kind=self.group_type, name__value=group_name, include=["members"])
96
+ group = await self.client.get(
97
+ kind=self.group_type, name__value=group_name, include=["members"], branch=self.branch
98
+ )
91
99
  except NodeNotFoundError:
92
100
  return None
93
101
 
94
102
  if not store_peers:
95
103
  return group
96
104
 
97
- self.previous_members = group.members.peers # type: ignore[attr-defined]
105
+ self.previous_members = group._get_relationship_many(name="members").peers
98
106
  return group
99
107
 
100
108
  async def delete_unused(self) -> None:
@@ -151,6 +159,8 @@ class InfrahubGroupContext(InfrahubGroupContextBase):
151
159
  name=group_name,
152
160
  description=description,
153
161
  members=members,
162
+ branch=self.branch,
163
+ **self.group_params,
154
164
  )
155
165
  await group.save(allow_upsert=True, update_group_context=False)
156
166
 
@@ -186,7 +196,7 @@ class InfrahubGroupContextSync(InfrahubGroupContextBase):
186
196
  if not store_peers:
187
197
  return group
188
198
 
189
- self.previous_members = group.members.peers # type: ignore[attr-defined]
199
+ self.previous_members = group._get_relationship_many(name="members").peers
190
200
  return group
191
201
 
192
202
  def delete_unused(self) -> None:
@@ -243,6 +253,8 @@ class InfrahubGroupContextSync(InfrahubGroupContextBase):
243
253
  name=group_name,
244
254
  description=description,
245
255
  members=members,
256
+ branch=self.branch,
257
+ **self.group_params,
246
258
  )
247
259
  group.save(allow_upsert=True, update_group_context=False)
248
260
 
@@ -49,6 +49,7 @@ class AttributeKind(str, Enum):
49
49
  TEXTAREA = "TextArea"
50
50
  DATETIME = "DateTime"
51
51
  NUMBER = "Number"
52
+ NUMBERPOOL = "NumberPool"
52
53
  DROPDOWN = "Dropdown"
53
54
  EMAIL = "Email"
54
55
  PASSWORD = "Password" # noqa: S105
@@ -147,6 +147,18 @@ class InfrahubRepositoryGraphQLConfig(InfrahubRepositoryConfigElement):
147
147
  return file.read()
148
148
 
149
149
 
150
+ class InfrahubObjectConfig(InfrahubRepositoryConfigElement):
151
+ model_config = ConfigDict(extra="forbid")
152
+ name: str = Field(..., description="The name associated to the object file")
153
+ file_path: Path = Field(..., description="The file within the repository containing object data.")
154
+
155
+
156
+ class InfrahubMenuConfig(InfrahubRepositoryConfigElement):
157
+ model_config = ConfigDict(extra="forbid")
158
+ name: str = Field(..., description="The name of the menu")
159
+ file_path: Path = Field(..., description="The file within the repository containing menu data.")
160
+
161
+
150
162
  RESOURCE_MAP: dict[Any, str] = {
151
163
  InfrahubJinja2TransformConfig: "jinja2_transforms",
152
164
  InfrahubCheckDefinitionConfig: "check_definitions",
@@ -154,6 +166,8 @@ RESOURCE_MAP: dict[Any, str] = {
154
166
  InfrahubPythonTransformConfig: "python_transforms",
155
167
  InfrahubGeneratorDefinitionConfig: "generator_definitions",
156
168
  InfrahubRepositoryGraphQLConfig: "queries",
169
+ InfrahubObjectConfig: "objects",
170
+ InfrahubMenuConfig: "menus",
157
171
  }
158
172
 
159
173
 
@@ -176,6 +190,8 @@ class InfrahubRepositoryConfig(BaseModel):
176
190
  default_factory=list, description="Generator definitions"
177
191
  )
178
192
  queries: list[InfrahubRepositoryGraphQLConfig] = Field(default_factory=list, description="GraphQL Queries")
193
+ objects: list[Path] = Field(default_factory=list, description="Objects")
194
+ menus: list[Path] = Field(default_factory=list, description="Menus")
179
195
 
180
196
  @field_validator(
181
197
  "check_definitions",
@@ -459,7 +459,7 @@ class InfrahubObjectFileData(BaseModel):
459
459
  await node.save(allow_upsert=True)
460
460
 
461
461
  display_label = node.get_human_friendly_id_as_string() or f"{node.get_kind()} : {node.id}"
462
- client.log.info(f"Node: {display_label}")
462
+ client.log.info(f"Created node: {display_label}")
463
463
 
464
464
  for rel in remaining_rels:
465
465
  context = {}
infrahub_sdk/store.py CHANGED
@@ -4,7 +4,7 @@ import warnings
4
4
  from typing import TYPE_CHECKING, Literal, overload
5
5
 
6
6
  from .exceptions import NodeInvalidError, NodeNotFoundError
7
- from .node import parse_human_friendly_id
7
+ from .node.parsers import parse_human_friendly_id
8
8
 
9
9
  if TYPE_CHECKING:
10
10
  from .client import SchemaType, SchemaTypeSync
@@ -48,6 +48,7 @@ class SchemaCarPerson:
48
48
  namespace=NAMESPACE,
49
49
  include_in_menu=True,
50
50
  label="Person",
51
+ default_filter="name__value",
51
52
  human_friendly_id=["name__value"],
52
53
  attributes=[
53
54
  Attr(name="name", kind=AttributeKind.TEXT, unique=True),
infrahub_sdk/utils.py CHANGED
@@ -240,21 +240,6 @@ def is_valid_url(url: str) -> bool:
240
240
  return False
241
241
 
242
242
 
243
- def find_files(extension: str | list[str], directory: str | Path = ".") -> list[Path]:
244
- files: list[Path] = []
245
-
246
- if isinstance(extension, str):
247
- extension = [extension]
248
- if isinstance(directory, str):
249
- directory = Path(directory)
250
-
251
- for ext in extension:
252
- files.extend(list(directory.glob(f"**/*.{ext}")))
253
- files.extend(list(directory.glob(f"**/.*.{ext}")))
254
-
255
- return files
256
-
257
-
258
243
  def get_branch(branch: str | None = None, directory: str | Path = ".") -> str:
259
244
  """If branch isn't provide, return the name of the local Git branch."""
260
245
  if branch:
@@ -351,14 +336,16 @@ def write_to_file(path: Path, value: Any) -> bool:
351
336
  return written is not None
352
337
 
353
338
 
354
- def read_file(file_name: Path) -> str:
355
- if not file_name.is_file():
356
- raise FileNotValidError(name=str(file_name), message=f"{file_name} is not a valid file")
339
+ def read_file(file_path: Path) -> str:
340
+ if not file_path.is_file():
341
+ raise FileNotValidError(name=str(file_path.name), message=f"{file_path.name}: not found at {file_path.parent}")
357
342
  try:
358
- with Path.open(file_name, encoding="utf-8") as fobj:
343
+ with Path.open(file_path, encoding="utf-8") as fobj:
359
344
  return fobj.read()
360
345
  except UnicodeDecodeError as exc:
361
- raise FileNotValidError(name=str(file_name), message=f"Unable to read {file_name} with utf-8 encoding") from exc
346
+ raise FileNotValidError(
347
+ name=str(file_path.name), message=f"Unable to read {file_path.name} with utf-8 encoding"
348
+ ) from exc
362
349
 
363
350
 
364
351
  def get_user_permissions(data: list[dict]) -> dict:
infrahub_sdk/yaml.py CHANGED
@@ -10,7 +10,7 @@ from typing_extensions import Self
10
10
  from yaml.parser import ParserError
11
11
 
12
12
  from .exceptions import FileNotValidError
13
- from .utils import find_files, read_file
13
+ from .utils import read_file
14
14
 
15
15
 
16
16
  class InfrahubFileApiVersion(str, Enum):
@@ -121,12 +121,13 @@ class YamlFile(LocalFile):
121
121
  def load_from_disk(cls, paths: list[Path]) -> list[Self]:
122
122
  yaml_files: list[Self] = []
123
123
  for file_path in paths:
124
- if file_path.is_file():
124
+ if file_path.is_file() and file_path.suffix in [".yaml", ".yml", ".json"]:
125
125
  yaml_files.extend(cls.load_file_from_disk(path=file_path))
126
126
  elif file_path.is_dir():
127
- files = find_files(extension=["yaml", "yml", "json"], directory=file_path)
128
- for item in files:
129
- yaml_files.extend(cls.load_file_from_disk(path=item))
127
+ sub_paths = [Path(sub_file_path) for sub_file_path in file_path.glob("*")]
128
+ sub_files = cls.load_from_disk(paths=sub_paths)
129
+ sorted_sub_files = sorted(sub_files, key=lambda x: x.location)
130
+ yaml_files.extend(sorted_sub_files)
130
131
  else:
131
132
  raise FileNotValidError(name=str(file_path), message=f"{file_path} does not exist!")
132
133
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: infrahub-server
3
- Version: 1.2.12
3
+ Version: 1.3.0
4
4
  Summary: Infrahub is taking a new approach to Infrastructure Management by providing a new generation of datastore to organize and control all the data that defines how an infrastructure should run.
5
5
  License: AGPL-3.0-only
6
6
  Author: OpsMill
@@ -38,7 +38,7 @@ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc (==1.28.1)
38
38
  Requires-Dist: opentelemetry-exporter-otlp-proto-http (==1.28.1)
39
39
  Requires-Dist: opentelemetry-instrumentation-aio-pika (==0.49b1)
40
40
  Requires-Dist: opentelemetry-instrumentation-fastapi (==0.49b1)
41
- Requires-Dist: prefect (==3.3.7)
41
+ Requires-Dist: prefect (==3.4.1)
42
42
  Requires-Dist: prefect-redis (==0.2.2)
43
43
  Requires-Dist: pyarrow (>=14,<15)
44
44
  Requires-Dist: pydantic (>=2.10,<2.11)
@@ -55,7 +55,7 @@ Requires-Dist: toml (>=0.10,<0.11)
55
55
  Requires-Dist: typer (==0.12.5)
56
56
  Requires-Dist: ujson (>=5,<6)
57
57
  Requires-Dist: uvicorn[standard] (>=0.32,<0.33)
58
- Requires-Dist: whenever (==0.7.2)
58
+ Requires-Dist: whenever (==0.7.3)
59
59
  Project-URL: Documentation, https://docs.infrahub.app/
60
60
  Project-URL: Homepage, https://opsmill.com
61
61
  Project-URL: Repository, https://github.com/opsmill/infrahub