infrahub-server 1.6.3__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 (250) 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 +4 -4
  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 +21 -2
  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 +5 -3
  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_schema.py +2 -2
  104. infrahub/core/schema/basenode_schema.py +3 -0
  105. infrahub/core/schema/definitions/core/__init__.py +8 -2
  106. infrahub/core/schema/definitions/core/account.py +10 -10
  107. infrahub/core/schema/definitions/core/artifact.py +14 -8
  108. infrahub/core/schema/definitions/core/check.py +10 -4
  109. infrahub/core/schema/definitions/core/generator.py +26 -6
  110. infrahub/core/schema/definitions/core/graphql_query.py +1 -1
  111. infrahub/core/schema/definitions/core/group.py +9 -2
  112. infrahub/core/schema/definitions/core/ipam.py +80 -10
  113. infrahub/core/schema/definitions/core/menu.py +41 -7
  114. infrahub/core/schema/definitions/core/permission.py +16 -2
  115. infrahub/core/schema/definitions/core/profile.py +16 -2
  116. infrahub/core/schema/definitions/core/propose_change.py +24 -4
  117. infrahub/core/schema/definitions/core/propose_change_comment.py +23 -11
  118. infrahub/core/schema/definitions/core/propose_change_validator.py +50 -21
  119. infrahub/core/schema/definitions/core/repository.py +10 -0
  120. infrahub/core/schema/definitions/core/resource_pool.py +8 -1
  121. infrahub/core/schema/definitions/core/template.py +19 -2
  122. infrahub/core/schema/definitions/core/transform.py +11 -5
  123. infrahub/core/schema/definitions/core/webhook.py +27 -9
  124. infrahub/core/schema/manager.py +63 -43
  125. infrahub/core/schema/relationship_schema.py +6 -2
  126. infrahub/core/schema/schema_branch.py +48 -10
  127. infrahub/core/task/task.py +4 -2
  128. infrahub/core/utils.py +3 -25
  129. infrahub/core/validators/aggregated_checker.py +1 -1
  130. infrahub/core/validators/attribute/choices.py +1 -1
  131. infrahub/core/validators/attribute/enum.py +1 -1
  132. infrahub/core/validators/attribute/kind.py +1 -1
  133. infrahub/core/validators/attribute/length.py +1 -1
  134. infrahub/core/validators/attribute/min_max.py +1 -1
  135. infrahub/core/validators/attribute/number_pool.py +1 -1
  136. infrahub/core/validators/attribute/optional.py +1 -1
  137. infrahub/core/validators/attribute/regex.py +1 -1
  138. infrahub/core/validators/determiner.py +3 -3
  139. infrahub/core/validators/node/attribute.py +1 -1
  140. infrahub/core/validators/node/relationship.py +1 -1
  141. infrahub/core/validators/relationship/peer.py +1 -1
  142. infrahub/database/__init__.py +4 -4
  143. infrahub/dependencies/builder/constraint/grouped/node_runner.py +2 -0
  144. infrahub/dependencies/builder/constraint/relationship_manager/profiles_removal.py +8 -0
  145. infrahub/dependencies/registry.py +2 -0
  146. infrahub/display_labels/tasks.py +12 -3
  147. infrahub/git/integrator.py +18 -18
  148. infrahub/git/tasks.py +1 -1
  149. infrahub/git/utils.py +1 -1
  150. infrahub/graphql/constants.py +3 -0
  151. infrahub/graphql/context.py +1 -1
  152. infrahub/graphql/field_extractor.py +1 -1
  153. infrahub/graphql/initialization.py +11 -0
  154. infrahub/graphql/loaders/account.py +134 -0
  155. infrahub/graphql/loaders/node.py +5 -12
  156. infrahub/graphql/loaders/peers.py +5 -7
  157. infrahub/graphql/manager.py +175 -21
  158. infrahub/graphql/metadata.py +91 -0
  159. infrahub/graphql/mutations/account.py +6 -6
  160. infrahub/graphql/mutations/attribute.py +0 -2
  161. infrahub/graphql/mutations/branch.py +9 -5
  162. infrahub/graphql/mutations/computed_attribute.py +1 -1
  163. infrahub/graphql/mutations/display_label.py +1 -1
  164. infrahub/graphql/mutations/hfid.py +1 -1
  165. infrahub/graphql/mutations/ipam.py +4 -6
  166. infrahub/graphql/mutations/main.py +9 -4
  167. infrahub/graphql/mutations/profile.py +16 -22
  168. infrahub/graphql/mutations/proposed_change.py +4 -4
  169. infrahub/graphql/mutations/relationship.py +40 -10
  170. infrahub/graphql/mutations/repository.py +14 -12
  171. infrahub/graphql/mutations/schema.py +2 -2
  172. infrahub/graphql/order.py +14 -0
  173. infrahub/graphql/queries/branch.py +62 -6
  174. infrahub/graphql/queries/resource_manager.py +25 -24
  175. infrahub/graphql/resolvers/account_metadata.py +84 -0
  176. infrahub/graphql/resolvers/ipam.py +6 -8
  177. infrahub/graphql/resolvers/many_relationship.py +77 -35
  178. infrahub/graphql/resolvers/resolver.py +59 -14
  179. infrahub/graphql/resolvers/single_relationship.py +87 -23
  180. infrahub/graphql/subscription/graphql_query.py +2 -0
  181. infrahub/graphql/types/__init__.py +0 -1
  182. infrahub/graphql/types/attribute.py +10 -5
  183. infrahub/graphql/types/branch.py +40 -53
  184. infrahub/graphql/types/enums.py +3 -0
  185. infrahub/graphql/types/metadata.py +28 -0
  186. infrahub/graphql/types/node.py +22 -2
  187. infrahub/graphql/types/relationship.py +10 -2
  188. infrahub/graphql/types/standard_node.py +12 -7
  189. infrahub/hfid/tasks.py +12 -3
  190. infrahub/lock.py +7 -0
  191. infrahub/menu/repository.py +1 -1
  192. infrahub/patch/queries/base.py +1 -1
  193. infrahub/pools/number.py +1 -8
  194. infrahub/profiles/gather.py +56 -0
  195. infrahub/profiles/mandatory_fields_checker.py +116 -0
  196. infrahub/profiles/models.py +66 -0
  197. infrahub/profiles/node_applier.py +154 -13
  198. infrahub/profiles/queries/get_profile_data.py +143 -31
  199. infrahub/profiles/tasks.py +79 -27
  200. infrahub/profiles/triggers.py +22 -0
  201. infrahub/proposed_change/action_checker.py +1 -1
  202. infrahub/proposed_change/tasks.py +4 -1
  203. infrahub/services/__init__.py +1 -1
  204. infrahub/services/adapters/cache/nats.py +1 -1
  205. infrahub/services/adapters/cache/redis.py +7 -0
  206. infrahub/tasks/artifact.py +1 -0
  207. infrahub/transformations/tasks.py +2 -2
  208. infrahub/trigger/catalogue.py +2 -0
  209. infrahub/trigger/models.py +1 -0
  210. infrahub/trigger/setup.py +3 -3
  211. infrahub/trigger/tasks.py +3 -0
  212. infrahub/validators/tasks.py +1 -0
  213. infrahub/webhook/gather.py +1 -1
  214. infrahub/webhook/models.py +1 -1
  215. infrahub/webhook/tasks.py +23 -7
  216. infrahub/workers/dependencies.py +9 -3
  217. infrahub/workers/infrahub_async.py +13 -4
  218. infrahub/workflows/catalogue.py +19 -0
  219. infrahub_sdk/analyzer.py +2 -2
  220. infrahub_sdk/branch.py +12 -39
  221. infrahub_sdk/checks.py +4 -4
  222. infrahub_sdk/client.py +36 -0
  223. infrahub_sdk/ctl/cli_commands.py +2 -1
  224. infrahub_sdk/ctl/graphql.py +15 -4
  225. infrahub_sdk/ctl/utils.py +2 -2
  226. infrahub_sdk/enums.py +6 -0
  227. infrahub_sdk/graphql/renderers.py +21 -0
  228. infrahub_sdk/graphql/utils.py +85 -0
  229. infrahub_sdk/node/attribute.py +12 -2
  230. infrahub_sdk/node/constants.py +12 -0
  231. infrahub_sdk/node/metadata.py +69 -0
  232. infrahub_sdk/node/node.py +65 -14
  233. infrahub_sdk/node/property.py +3 -0
  234. infrahub_sdk/node/related_node.py +37 -5
  235. infrahub_sdk/node/relationship.py +18 -1
  236. infrahub_sdk/operation.py +2 -2
  237. infrahub_sdk/schema/repository.py +1 -2
  238. infrahub_sdk/transforms.py +2 -2
  239. infrahub_sdk/types.py +18 -2
  240. {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/METADATA +17 -16
  241. {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/RECORD +249 -228
  242. infrahub_testcontainers/container.py +3 -3
  243. infrahub_testcontainers/docker-compose-cluster.test.yml +7 -7
  244. infrahub_testcontainers/docker-compose.test.yml +13 -5
  245. infrahub_testcontainers/models.py +3 -3
  246. infrahub_testcontainers/performance_test.py +1 -1
  247. infrahub/graphql/models.py +0 -6
  248. {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/WHEEL +0 -0
  249. {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/entry_points.txt +0 -0
  250. {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/licenses/LICENSE.txt +0 -0
infrahub/webhook/tasks.py CHANGED
@@ -13,7 +13,7 @@ from prefect.logging import get_run_logger
13
13
 
14
14
  from infrahub.message_bus.types import KVTTL
15
15
  from infrahub.trigger.models import TriggerType
16
- from infrahub.trigger.setup import setup_triggers_specific
16
+ from infrahub.trigger.setup import gather_all_automations, setup_triggers_specific
17
17
  from infrahub.workers.dependencies import get_cache, get_client, get_database, get_http
18
18
  from infrahub.workflows.utils import add_tags
19
19
 
@@ -118,12 +118,12 @@ async def configure_webhook_all() -> None:
118
118
  triggers = await gather_trigger_webhook(db=db)
119
119
 
120
120
  log.info(f"{len(triggers)} Webhooks automation configuration completed")
121
- await setup_triggers_specific(gatherer=gather_trigger_webhook, db=database, trigger_type=TriggerType.WEBHOOK) # type: ignore[misc]
121
+ await setup_triggers_specific(gatherer=gather_trigger_webhook, db=database, trigger_type=TriggerType.WEBHOOK) # type: ignore[arg-type]
122
122
 
123
123
 
124
124
  @flow(name="webhook-setup-automation-one", flow_run_name="Configurate webhook for {webhook_name}")
125
125
  async def configure_webhook_one(
126
- webhook_name: str, # noqa: ARG001
126
+ webhook_name: str,
127
127
  event_data: dict,
128
128
  ) -> None:
129
129
  log = get_run_logger()
@@ -132,6 +132,24 @@ async def configure_webhook_one(
132
132
  trigger = WebhookTriggerDefinition.from_object(webhook)
133
133
 
134
134
  async with get_prefect_client(sync_client=False) as prefect_client:
135
+ all_automations = await gather_all_automations(client=prefect_client)
136
+ existing_automations = [
137
+ automation for automation in all_automations if automation.name == trigger.generate_name()
138
+ ]
139
+ existing_automation = existing_automations[0] if existing_automations else None
140
+
141
+ # If webhook is inactive, delete the automation if it exists
142
+ if not webhook.active.value:
143
+ if existing_automation:
144
+ await prefect_client.delete_automation(automation_id=existing_automation.id)
145
+ log.info(f"Automation {trigger.generate_name()} deleted (webhook disabled)")
146
+ else:
147
+ log.info(f"Webhook {webhook_name} is disabled, no automation to delete")
148
+
149
+ cache = await get_cache()
150
+ await cache.delete(key=f"webhook:{webhook.id}")
151
+ return
152
+
135
153
  # Query the deployment associated with the trigger to have its ID
136
154
  deployment_name = trigger.get_deployment_names()[0]
137
155
  deployment = await prefect_client.read_deployment_by_name(name=f"{deployment_name}/{deployment_name}")
@@ -144,9 +162,6 @@ async def configure_webhook_one(
144
162
  actions=[action.get(deployment.id) for action in trigger.actions],
145
163
  )
146
164
 
147
- existing_automations = await prefect_client.read_automations_by_name(trigger.generate_name())
148
- existing_automation = existing_automations[0] if existing_automations else None
149
-
150
165
  if existing_automation:
151
166
  await prefect_client.update_automation(automation_id=existing_automation.id, automation=automation)
152
167
  log.info(f"Automation {trigger.generate_name()} updated")
@@ -168,7 +183,8 @@ async def delete_webhook_automation(
168
183
  async with get_prefect_client(sync_client=False) as prefect_client:
169
184
  automation_name = WebhookTriggerDefinition.generate_name_from_id(id=webhook_id)
170
185
 
171
- existing_automations = await prefect_client.read_automations_by_name(automation_name)
186
+ all_automations = await gather_all_automations(client=prefect_client)
187
+ existing_automations = [automation for automation in all_automations if automation.name == automation_name]
172
188
  existing_automation = existing_automations[0] if existing_automations else None
173
189
 
174
190
  if existing_automation:
@@ -60,9 +60,15 @@ def get_installation_type(installation_type: str = Depends(build_installation_ty
60
60
  return installation_type
61
61
 
62
62
 
63
- async def build_database() -> InfrahubDatabase:
64
- if "database" not in _singletons:
65
- _singletons["database"] = InfrahubDatabase(driver=await get_db(retry=5))
63
+ async def build_database(singleton: bool = True) -> InfrahubDatabase:
64
+ if not singleton or "database" not in _singletons:
65
+ db = InfrahubDatabase(driver=await get_db(retry=5))
66
+
67
+ if singleton:
68
+ _singletons["database"] = db
69
+
70
+ return db
71
+
66
72
  return _singletons["database"]
67
73
 
68
74
 
@@ -24,6 +24,7 @@ from infrahub.core import registry
24
24
  from infrahub.core.initialization import initialization
25
25
  from infrahub.database.graph import validate_graph_version
26
26
  from infrahub.dependencies.registry import build_component_registry
27
+ from infrahub.exceptions import InitializationError
27
28
  from infrahub.git import initialize_repositories_directory
28
29
  from infrahub.lock import initialize_lock
29
30
  from infrahub.services import InfrahubServices
@@ -182,9 +183,17 @@ class InfrahubWorkerAsync(BaseWorker):
182
183
  async def _init_infrahub_client(self, client: InfrahubClient | None = None) -> InfrahubClient:
183
184
  if not client:
184
185
  self._logger.debug(f"Using Infrahub API at {config.SETTINGS.main.internal_address}")
185
- client = InfrahubClient(
186
- config=Config(address=config.SETTINGS.main.internal_address, retry_on_failure=True, log=self._logger)
187
- )
186
+ try:
187
+ client = InfrahubClient(
188
+ config=Config(
189
+ address=config.SETTINGS.main.infrahub_address, retry_on_failure=True, log=self._logger
190
+ )
191
+ )
192
+ except InitializationError as err:
193
+ self._logger.error(
194
+ "Infrahub client initialization failed due to missing configuration for internal_address."
195
+ )
196
+ raise typer.Exit(1) from err
188
197
 
189
198
  try:
190
199
  await client.branch.all()
@@ -194,7 +203,7 @@ class InfrahubWorkerAsync(BaseWorker):
194
203
 
195
204
  return client
196
205
 
197
- async def _init_services(self, client: InfrahubClient) -> None:
206
+ async def _init_services(self, client: InfrahubClient | None) -> None:
198
207
  client = await self._init_infrahub_client(client=client)
199
208
 
200
209
  service = await InfrahubServices.new(
@@ -623,6 +623,23 @@ PROFILE_REFRESH = WorkflowDefinition(
623
623
  )
624
624
 
625
625
 
626
+ PROFILE_REFRESH_SETUP = WorkflowDefinition(
627
+ name="profile-refresh-setup",
628
+ type=WorkflowType.CORE,
629
+ module="infrahub.profiles.tasks",
630
+ function="profile_refresh_setup",
631
+ )
632
+
633
+
634
+ PROFILE_REFRESH_PROCESS = WorkflowDefinition(
635
+ name="profile-refresh-process",
636
+ type=WorkflowType.CORE,
637
+ module="infrahub.profiles.tasks",
638
+ function="profile_refresh_process",
639
+ tags=[WorkflowTag.DATABASE_CHANGE],
640
+ )
641
+
642
+
626
643
  CLEAN_UP_DEADLOCKS = WorkflowDefinition(
627
644
  name="clean-up-deadlocks",
628
645
  type=WorkflowType.INTERNAL,
@@ -685,6 +702,8 @@ WORKFLOWS = [
685
702
  IPAM_RECONCILIATION,
686
703
  PROFILE_REFRESH,
687
704
  PROFILE_REFRESH_MULTIPLE,
705
+ PROFILE_REFRESH_PROCESS,
706
+ PROFILE_REFRESH_SETUP,
688
707
  PROPOSED_CHANGE_MERGE,
689
708
  QUERY_COMPUTED_ATTRIBUTE_TRANSFORM_TARGETS,
690
709
  REMOVE_ADD_NODE_FROM_GROUP,
infrahub_sdk/analyzer.py CHANGED
@@ -30,10 +30,10 @@ class GraphQLOperation(BaseModel):
30
30
 
31
31
 
32
32
  class GraphQLQueryAnalyzer:
33
- def __init__(self, query: str, schema: GraphQLSchema | None = None) -> None:
33
+ def __init__(self, query: str, schema: GraphQLSchema | None = None, document: DocumentNode | None = None) -> None:
34
34
  self.query: str = query
35
35
  self.schema: GraphQLSchema | None = schema
36
- self.document: DocumentNode = parse(self.query)
36
+ self.document: DocumentNode = document or parse(self.query)
37
37
  self._fields: dict | None = None
38
38
 
39
39
  @property
infrahub_sdk/branch.py CHANGED
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import warnings
4
3
  from enum import Enum
5
4
  from typing import TYPE_CHECKING, Any, Literal, overload
6
5
  from urllib.parse import urlencode
@@ -93,7 +92,6 @@ class InfrahubBranchManager(InfraHubBranchManagerBase):
93
92
  sync_with_git: bool = True,
94
93
  description: str = "",
95
94
  wait_until_completion: Literal[True] = True,
96
- background_execution: bool | None = False,
97
95
  ) -> BranchData: ...
98
96
 
99
97
  @overload
@@ -103,7 +101,6 @@ class InfrahubBranchManager(InfraHubBranchManagerBase):
103
101
  sync_with_git: bool = True,
104
102
  description: str = "",
105
103
  wait_until_completion: Literal[False] = False,
106
- background_execution: bool | None = False,
107
104
  ) -> str: ...
108
105
 
109
106
  async def create(
@@ -112,19 +109,9 @@ class InfrahubBranchManager(InfraHubBranchManagerBase):
112
109
  sync_with_git: bool = True,
113
110
  description: str = "",
114
111
  wait_until_completion: bool = True,
115
- background_execution: bool | None = False,
116
112
  ) -> BranchData | str:
117
- if background_execution is not None:
118
- warnings.warn(
119
- "`background_execution` is deprecated, please use `wait_until_completion` instead.",
120
- DeprecationWarning,
121
- stacklevel=1,
122
- )
123
-
124
- background_execution = background_execution or not wait_until_completion
125
113
  input_data = {
126
- # Should be switched to `wait_until_completion` once `background_execution` is removed server side.
127
- "background_execution": background_execution,
114
+ "wait_until_completion": wait_until_completion,
128
115
  "data": {
129
116
  "name": branch_name,
130
117
  "description": description,
@@ -132,15 +119,14 @@ class InfrahubBranchManager(InfraHubBranchManagerBase):
132
119
  },
133
120
  }
134
121
 
135
- mutation_query = MUTATION_QUERY_TASK if background_execution else MUTATION_QUERY_DATA
122
+ mutation_query = MUTATION_QUERY_DATA if wait_until_completion else MUTATION_QUERY_TASK
136
123
  query = Mutation(mutation="BranchCreate", input_data=input_data, query=mutation_query)
137
124
  response = await self.client.execute_graphql(query=query.render(), tracker="mutation-branch-create")
138
125
 
139
- # Make sure server version is recent enough to support background execution, as previously
140
- # using background_execution=True had no effect.
141
- if background_execution and "task" in response["BranchCreate"]:
142
- return response["BranchCreate"]["task"]["id"]
143
- return BranchData(**response["BranchCreate"]["object"])
126
+ if wait_until_completion:
127
+ return BranchData(**response["BranchCreate"]["object"])
128
+
129
+ return response["BranchCreate"]["task"]["id"]
144
130
 
145
131
  async def delete(self, branch_name: str) -> bool:
146
132
  input_data = {
@@ -261,7 +247,6 @@ class InfrahubBranchManagerSync(InfraHubBranchManagerBase):
261
247
  sync_with_git: bool = True,
262
248
  description: str = "",
263
249
  wait_until_completion: Literal[True] = True,
264
- background_execution: bool | None = False,
265
250
  ) -> BranchData: ...
266
251
 
267
252
  @overload
@@ -271,7 +256,6 @@ class InfrahubBranchManagerSync(InfraHubBranchManagerBase):
271
256
  sync_with_git: bool = True,
272
257
  description: str = "",
273
258
  wait_until_completion: Literal[False] = False,
274
- background_execution: bool | None = False,
275
259
  ) -> str: ...
276
260
 
277
261
  def create(
@@ -280,19 +264,9 @@ class InfrahubBranchManagerSync(InfraHubBranchManagerBase):
280
264
  sync_with_git: bool = True,
281
265
  description: str = "",
282
266
  wait_until_completion: bool = True,
283
- background_execution: bool | None = False,
284
267
  ) -> BranchData | str:
285
- if background_execution is not None:
286
- warnings.warn(
287
- "`background_execution` is deprecated, please use `wait_until_completion` instead.",
288
- DeprecationWarning,
289
- stacklevel=1,
290
- )
291
-
292
- background_execution = background_execution or not wait_until_completion
293
268
  input_data = {
294
- # Should be switched to `wait_until_completion` once `background_execution` is removed server side.
295
- "background_execution": background_execution,
269
+ "wait_until_completion": wait_until_completion,
296
270
  "data": {
297
271
  "name": branch_name,
298
272
  "description": description,
@@ -300,15 +274,14 @@ class InfrahubBranchManagerSync(InfraHubBranchManagerBase):
300
274
  },
301
275
  }
302
276
 
303
- mutation_query = MUTATION_QUERY_TASK if background_execution else MUTATION_QUERY_DATA
277
+ mutation_query = MUTATION_QUERY_DATA if wait_until_completion else MUTATION_QUERY_TASK
304
278
  query = Mutation(mutation="BranchCreate", input_data=input_data, query=mutation_query)
305
279
  response = self.client.execute_graphql(query=query.render(), tracker="mutation-branch-create")
306
280
 
307
- # Make sure server version is recent enough to support background execution, as previously
308
- # using background_execution=True had no effect.
309
- if background_execution and "task" in response["BranchCreate"]:
310
- return response["BranchCreate"]["task"]["id"]
311
- return BranchData(**response["BranchCreate"]["object"])
281
+ if wait_until_completion:
282
+ return BranchData(**response["BranchCreate"]["object"])
283
+
284
+ return response["BranchCreate"]["task"]["id"]
312
285
 
313
286
  def delete(self, branch_name: str) -> bool:
314
287
  input_data = {
infrahub_sdk/checks.py CHANGED
@@ -1,8 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- import asyncio
4
3
  import importlib
5
- import os
4
+ import inspect
5
+ import pathlib
6
6
  import warnings
7
7
  from abc import abstractmethod
8
8
  from typing import TYPE_CHECKING, Any
@@ -55,7 +55,7 @@ class InfrahubCheck:
55
55
  self.branch = branch
56
56
  self.params = params or {}
57
57
 
58
- self.root_directory = root_directory or os.getcwd()
58
+ self.root_directory = root_directory or str(pathlib.Path.cwd())
59
59
 
60
60
  self._client = client
61
61
 
@@ -160,7 +160,7 @@ class InfrahubCheck:
160
160
  data = await self.collect_data()
161
161
  unpacked = data.get("data") or data
162
162
 
163
- if asyncio.iscoroutinefunction(self.validate):
163
+ if inspect.iscoroutinefunction(self.validate):
164
164
  await self.validate(data=unpacked)
165
165
  else:
166
166
  self.validate(data=unpacked)
infrahub_sdk/client.py CHANGED
@@ -401,6 +401,7 @@ class InfrahubClient(BaseClient):
401
401
  fragment: bool = ...,
402
402
  prefetch_relationships: bool = ...,
403
403
  property: bool = ...,
404
+ include_metadata: bool = ...,
404
405
  **kwargs: Any,
405
406
  ) -> SchemaType | None: ...
406
407
 
@@ -420,6 +421,7 @@ class InfrahubClient(BaseClient):
420
421
  fragment: bool = ...,
421
422
  prefetch_relationships: bool = ...,
422
423
  property: bool = ...,
424
+ include_metadata: bool = ...,
423
425
  **kwargs: Any,
424
426
  ) -> SchemaType: ...
425
427
 
@@ -439,6 +441,7 @@ class InfrahubClient(BaseClient):
439
441
  fragment: bool = ...,
440
442
  prefetch_relationships: bool = ...,
441
443
  property: bool = ...,
444
+ include_metadata: bool = ...,
442
445
  **kwargs: Any,
443
446
  ) -> SchemaType: ...
444
447
 
@@ -458,6 +461,7 @@ class InfrahubClient(BaseClient):
458
461
  fragment: bool = ...,
459
462
  prefetch_relationships: bool = ...,
460
463
  property: bool = ...,
464
+ include_metadata: bool = ...,
461
465
  **kwargs: Any,
462
466
  ) -> InfrahubNode | None: ...
463
467
 
@@ -477,6 +481,7 @@ class InfrahubClient(BaseClient):
477
481
  fragment: bool = ...,
478
482
  prefetch_relationships: bool = ...,
479
483
  property: bool = ...,
484
+ include_metadata: bool = ...,
480
485
  **kwargs: Any,
481
486
  ) -> InfrahubNode: ...
482
487
 
@@ -496,6 +501,7 @@ class InfrahubClient(BaseClient):
496
501
  fragment: bool = ...,
497
502
  prefetch_relationships: bool = ...,
498
503
  property: bool = ...,
504
+ include_metadata: bool = ...,
499
505
  **kwargs: Any,
500
506
  ) -> InfrahubNode: ...
501
507
 
@@ -514,6 +520,7 @@ class InfrahubClient(BaseClient):
514
520
  fragment: bool = False,
515
521
  prefetch_relationships: bool = False,
516
522
  property: bool = False,
523
+ include_metadata: bool = False,
517
524
  **kwargs: Any,
518
525
  ) -> InfrahubNode | SchemaType | None:
519
526
  branch = branch or self.default_branch
@@ -547,6 +554,7 @@ class InfrahubClient(BaseClient):
547
554
  fragment=fragment,
548
555
  prefetch_relationships=prefetch_relationships,
549
556
  property=property,
557
+ include_metadata=include_metadata,
550
558
  **filters,
551
559
  )
552
560
 
@@ -650,6 +658,7 @@ class InfrahubClient(BaseClient):
650
658
  property: bool = ...,
651
659
  parallel: bool = ...,
652
660
  order: Order | None = ...,
661
+ include_metadata: bool = ...,
653
662
  ) -> list[SchemaType]: ...
654
663
 
655
664
  @overload
@@ -669,6 +678,7 @@ class InfrahubClient(BaseClient):
669
678
  property: bool = ...,
670
679
  parallel: bool = ...,
671
680
  order: Order | None = ...,
681
+ include_metadata: bool = ...,
672
682
  ) -> list[InfrahubNode]: ...
673
683
 
674
684
  async def all(
@@ -687,6 +697,7 @@ class InfrahubClient(BaseClient):
687
697
  property: bool = False,
688
698
  parallel: bool = False,
689
699
  order: Order | None = None,
700
+ include_metadata: bool = False,
690
701
  ) -> list[InfrahubNode] | list[SchemaType]:
691
702
  """Retrieve all nodes of a given kind
692
703
 
@@ -704,6 +715,7 @@ class InfrahubClient(BaseClient):
704
715
  prefetch_relationships (bool, optional): Flag to indicate whether to prefetch related node data.
705
716
  parallel (bool, optional): Whether to use parallel processing for the query.
706
717
  order (Order, optional): Ordering related options. Setting `disable=True` enhances performances.
718
+ include_metadata (bool, optional): If True, includes node_metadata and relationship_metadata in the query.
707
719
 
708
720
  Returns:
709
721
  list[InfrahubNode]: List of Nodes
@@ -723,6 +735,7 @@ class InfrahubClient(BaseClient):
723
735
  property=property,
724
736
  parallel=parallel,
725
737
  order=order,
738
+ include_metadata=include_metadata,
726
739
  )
727
740
 
728
741
  @overload
@@ -743,6 +756,7 @@ class InfrahubClient(BaseClient):
743
756
  property: bool = ...,
744
757
  parallel: bool = ...,
745
758
  order: Order | None = ...,
759
+ include_metadata: bool = ...,
746
760
  **kwargs: Any,
747
761
  ) -> list[SchemaType]: ...
748
762
 
@@ -764,6 +778,7 @@ class InfrahubClient(BaseClient):
764
778
  property: bool = ...,
765
779
  parallel: bool = ...,
766
780
  order: Order | None = ...,
781
+ include_metadata: bool = ...,
767
782
  **kwargs: Any,
768
783
  ) -> list[InfrahubNode]: ...
769
784
 
@@ -784,6 +799,7 @@ class InfrahubClient(BaseClient):
784
799
  property: bool = False,
785
800
  parallel: bool = False,
786
801
  order: Order | None = None,
802
+ include_metadata: bool = False,
787
803
  **kwargs: Any,
788
804
  ) -> list[InfrahubNode] | list[SchemaType]:
789
805
  """Retrieve nodes of a given kind based on provided filters.
@@ -803,6 +819,7 @@ class InfrahubClient(BaseClient):
803
819
  partial_match (bool, optional): Allow partial match of filter criteria for the query.
804
820
  parallel (bool, optional): Whether to use parallel processing for the query.
805
821
  order (Order, optional): Ordering related options. Setting `disable=True` enhances performances.
822
+ include_metadata (bool, optional): If True, includes node_metadata and relationship_metadata in the query.
806
823
  **kwargs (Any): Additional filter criteria for the query.
807
824
 
808
825
  Returns:
@@ -829,6 +846,7 @@ class InfrahubClient(BaseClient):
829
846
  partial_match=partial_match,
830
847
  property=property,
831
848
  order=order,
849
+ include_metadata=include_metadata,
832
850
  )
833
851
  query = Query(query=query_data)
834
852
  response = await self.execute_graphql(
@@ -1957,6 +1975,7 @@ class InfrahubClientSync(BaseClient):
1957
1975
  property: bool = ...,
1958
1976
  parallel: bool = ...,
1959
1977
  order: Order | None = ...,
1978
+ include_metadata: bool = ...,
1960
1979
  ) -> list[SchemaTypeSync]: ...
1961
1980
 
1962
1981
  @overload
@@ -1976,6 +1995,7 @@ class InfrahubClientSync(BaseClient):
1976
1995
  property: bool = ...,
1977
1996
  parallel: bool = ...,
1978
1997
  order: Order | None = ...,
1998
+ include_metadata: bool = ...,
1979
1999
  ) -> list[InfrahubNodeSync]: ...
1980
2000
 
1981
2001
  def all(
@@ -1994,6 +2014,7 @@ class InfrahubClientSync(BaseClient):
1994
2014
  property: bool = False,
1995
2015
  parallel: bool = False,
1996
2016
  order: Order | None = None,
2017
+ include_metadata: bool = False,
1997
2018
  ) -> list[InfrahubNodeSync] | list[SchemaTypeSync]:
1998
2019
  """Retrieve all nodes of a given kind
1999
2020
 
@@ -2011,6 +2032,7 @@ class InfrahubClientSync(BaseClient):
2011
2032
  prefetch_relationships (bool, optional): Flag to indicate whether to prefetch related node data.
2012
2033
  parallel (bool, optional): Whether to use parallel processing for the query.
2013
2034
  order (Order, optional): Ordering related options. Setting `disable=True` enhances performances.
2035
+ include_metadata (bool, optional): If True, includes node_metadata and relationship_metadata in the query.
2014
2036
 
2015
2037
  Returns:
2016
2038
  list[InfrahubNodeSync]: List of Nodes
@@ -2030,6 +2052,7 @@ class InfrahubClientSync(BaseClient):
2030
2052
  property=property,
2031
2053
  parallel=parallel,
2032
2054
  order=order,
2055
+ include_metadata=include_metadata,
2033
2056
  )
2034
2057
 
2035
2058
  def _process_nodes_and_relationships(
@@ -2091,6 +2114,7 @@ class InfrahubClientSync(BaseClient):
2091
2114
  property: bool = ...,
2092
2115
  parallel: bool = ...,
2093
2116
  order: Order | None = ...,
2117
+ include_metadata: bool = ...,
2094
2118
  **kwargs: Any,
2095
2119
  ) -> list[SchemaTypeSync]: ...
2096
2120
 
@@ -2112,6 +2136,7 @@ class InfrahubClientSync(BaseClient):
2112
2136
  property: bool = ...,
2113
2137
  parallel: bool = ...,
2114
2138
  order: Order | None = ...,
2139
+ include_metadata: bool = ...,
2115
2140
  **kwargs: Any,
2116
2141
  ) -> list[InfrahubNodeSync]: ...
2117
2142
 
@@ -2132,6 +2157,7 @@ class InfrahubClientSync(BaseClient):
2132
2157
  property: bool = False,
2133
2158
  parallel: bool = False,
2134
2159
  order: Order | None = None,
2160
+ include_metadata: bool = False,
2135
2161
  **kwargs: Any,
2136
2162
  ) -> list[InfrahubNodeSync] | list[SchemaTypeSync]:
2137
2163
  """Retrieve nodes of a given kind based on provided filters.
@@ -2151,6 +2177,7 @@ class InfrahubClientSync(BaseClient):
2151
2177
  partial_match (bool, optional): Allow partial match of filter criteria for the query.
2152
2178
  parallel (bool, optional): Whether to use parallel processing for the query.
2153
2179
  order (Order, optional): Ordering related options. Setting `disable=True` enhances performances.
2180
+ include_metadata (bool, optional): If True, includes node_metadata and relationship_metadata in the query.
2154
2181
  **kwargs (Any): Additional filter criteria for the query.
2155
2182
 
2156
2183
  Returns:
@@ -2177,6 +2204,7 @@ class InfrahubClientSync(BaseClient):
2177
2204
  partial_match=partial_match,
2178
2205
  property=property,
2179
2206
  order=order,
2207
+ include_metadata=include_metadata,
2180
2208
  )
2181
2209
  query = Query(query=query_data)
2182
2210
  response = self.execute_graphql(
@@ -2266,6 +2294,7 @@ class InfrahubClientSync(BaseClient):
2266
2294
  fragment: bool = ...,
2267
2295
  prefetch_relationships: bool = ...,
2268
2296
  property: bool = ...,
2297
+ include_metadata: bool = ...,
2269
2298
  **kwargs: Any,
2270
2299
  ) -> SchemaTypeSync | None: ...
2271
2300
 
@@ -2285,6 +2314,7 @@ class InfrahubClientSync(BaseClient):
2285
2314
  fragment: bool = ...,
2286
2315
  prefetch_relationships: bool = ...,
2287
2316
  property: bool = ...,
2317
+ include_metadata: bool = ...,
2288
2318
  **kwargs: Any,
2289
2319
  ) -> SchemaTypeSync: ...
2290
2320
 
@@ -2304,6 +2334,7 @@ class InfrahubClientSync(BaseClient):
2304
2334
  fragment: bool = ...,
2305
2335
  prefetch_relationships: bool = ...,
2306
2336
  property: bool = ...,
2337
+ include_metadata: bool = ...,
2307
2338
  **kwargs: Any,
2308
2339
  ) -> SchemaTypeSync: ...
2309
2340
 
@@ -2323,6 +2354,7 @@ class InfrahubClientSync(BaseClient):
2323
2354
  fragment: bool = ...,
2324
2355
  prefetch_relationships: bool = ...,
2325
2356
  property: bool = ...,
2357
+ include_metadata: bool = ...,
2326
2358
  **kwargs: Any,
2327
2359
  ) -> InfrahubNodeSync | None: ...
2328
2360
 
@@ -2342,6 +2374,7 @@ class InfrahubClientSync(BaseClient):
2342
2374
  fragment: bool = ...,
2343
2375
  prefetch_relationships: bool = ...,
2344
2376
  property: bool = ...,
2377
+ include_metadata: bool = ...,
2345
2378
  **kwargs: Any,
2346
2379
  ) -> InfrahubNodeSync: ...
2347
2380
 
@@ -2361,6 +2394,7 @@ class InfrahubClientSync(BaseClient):
2361
2394
  fragment: bool = ...,
2362
2395
  prefetch_relationships: bool = ...,
2363
2396
  property: bool = ...,
2397
+ include_metadata: bool = ...,
2364
2398
  **kwargs: Any,
2365
2399
  ) -> InfrahubNodeSync: ...
2366
2400
 
@@ -2379,6 +2413,7 @@ class InfrahubClientSync(BaseClient):
2379
2413
  fragment: bool = False,
2380
2414
  prefetch_relationships: bool = False,
2381
2415
  property: bool = False,
2416
+ include_metadata: bool = False,
2382
2417
  **kwargs: Any,
2383
2418
  ) -> InfrahubNodeSync | SchemaTypeSync | None:
2384
2419
  branch = branch or self.default_branch
@@ -2412,6 +2447,7 @@ class InfrahubClientSync(BaseClient):
2412
2447
  fragment=fragment,
2413
2448
  prefetch_relationships=prefetch_relationships,
2414
2449
  property=property,
2450
+ include_metadata=include_metadata,
2415
2451
  **filters,
2416
2452
  )
2417
2453
 
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  import asyncio
4
4
  import functools
5
5
  import importlib
6
+ import inspect
6
7
  import logging
7
8
  import platform
8
9
  import sys
@@ -240,7 +241,7 @@ async def _run_transform(
240
241
  console.print("[yellow] you can specify a different branch with --branch")
241
242
  raise typer.Abort()
242
243
 
243
- if asyncio.iscoroutinefunction(transform_func):
244
+ if inspect.iscoroutinefunction(transform_func):
244
245
  output = await transform_func(response)
245
246
  else:
246
247
  output = transform_func(response)
@@ -22,7 +22,12 @@ from rich.console import Console
22
22
  from ..async_typer import AsyncTyper
23
23
  from ..ctl.client import initialize_client
24
24
  from ..ctl.utils import catch_exception
25
- from ..graphql.utils import insert_fragments_inline, remove_fragment_import
25
+ from ..graphql.utils import (
26
+ insert_fragments_inline,
27
+ remove_fragment_import,
28
+ strip_typename_from_fragment,
29
+ strip_typename_from_operation,
30
+ )
26
31
  from .parameters import CONFIG_PARAM
27
32
 
28
33
  app = AsyncTyper()
@@ -152,12 +157,18 @@ async def generate_return_types(
152
157
  queries = filter_operations_definitions(definitions)
153
158
  fragments = filter_fragments_definitions(definitions)
154
159
 
160
+ # Strip __typename fields from operations and fragments before code generation.
161
+ # __typename is a GraphQL introspection meta-field that isn't part of the schema's
162
+ # type definitions, causing ariadne-codegen to fail with "Redefinition of reserved type 'String'"
163
+ stripped_queries = [strip_typename_from_operation(q) for q in queries]
164
+ stripped_fragments = [strip_typename_from_fragment(f) for f in fragments]
165
+
155
166
  package_generator = get_package_generator(
156
167
  schema=graphql_schema,
157
- fragments=fragments,
168
+ fragments=stripped_fragments,
158
169
  settings=ClientSettings(
159
170
  schema_path=str(schema),
160
- target_package_name=directory.name,
171
+ target_package_name=directory.name or "graphql_client",
161
172
  queries_path=str(directory),
162
173
  include_comments=CommentsStrategy.NONE,
163
174
  ),
@@ -166,7 +177,7 @@ async def generate_return_types(
166
177
 
167
178
  parsing_failed = False
168
179
  try:
169
- for query_operation in queries:
180
+ for query_operation in stripped_queries:
170
181
  package_generator.add_operation(query_operation)
171
182
  except ParsingError as exc:
172
183
  console.print(f"[red]Unable to process {gql_file.name}: {exc}")
infrahub_sdk/ctl/utils.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- import asyncio
3
+ import inspect
4
4
  import logging
5
5
  import traceback
6
6
  from collections.abc import Callable, Coroutine
@@ -83,7 +83,7 @@ def catch_exception(
83
83
  console = Console()
84
84
 
85
85
  def decorator(func: Callable[..., T]) -> Callable[..., T | Coroutine[Any, Any, T]]:
86
- if asyncio.iscoroutinefunction(func):
86
+ if inspect.iscoroutinefunction(func):
87
87
 
88
88
  @wraps(func)
89
89
  async def async_wrapper(*args: Any, **kwargs: Any) -> T: