infrahub-server 1.3.4__py3-none-any.whl → 1.3.5__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.
infrahub/cli/db.py CHANGED
@@ -916,5 +916,39 @@ async def run_database_checks(db: InfrahubDatabase, output_dir: Path) -> None:
916
916
  else:
917
917
  rprint(f"{SUCCESS_BADGE} No duplicated edges found")
918
918
 
919
+ # Check 4: Orphaned Relationships
920
+ rprint("\n[bold cyan]Check 4: Orphaned Relationships[/bold cyan]")
921
+ orphaned_rels_query = """
922
+ MATCH (r:Relationship)-[:IS_RELATED]-(peer:Node)
923
+ WITH DISTINCT r, peer
924
+ WITH r, count(*) AS num_peers
925
+ WHERE num_peers < 2
926
+ MATCH (r)-[e:IS_RELATED]-(peer:Node)
927
+ RETURN DISTINCT
928
+ r.name AS r_name,
929
+ e.branch AS branch,
930
+ e.status AS status,
931
+ e.from AS from_time,
932
+ e.to AS to_time,
933
+ peer.uuid AS peer_uuid,
934
+ peer.kind AS peer_kind
935
+ """
936
+ results = await db.execute_query(query=orphaned_rels_query)
937
+ if results:
938
+ rprint(f"[red]Found {len(results)} orphaned Relationships[/red]")
939
+ # Write detailed results to file
940
+ output_file = output_dir / "orphaned_relationships.csv"
941
+ with output_file.open(mode="w", newline="") as f:
942
+ writer = DictWriter(
943
+ f,
944
+ fieldnames=["r_name", "branch", "status", "from_time", "to_time", "peer_uuid", "peer_kind"],
945
+ )
946
+ writer.writeheader()
947
+ for result in results:
948
+ writer.writerow(dict(result))
949
+ rprint(f" Detailed results written to: {output_file}")
950
+ else:
951
+ rprint(f"{SUCCESS_BADGE} No orphaned relationships found")
952
+
919
953
  rprint(f"\n{SUCCESS_BADGE} Database health checks completed")
920
954
  rprint(f"Detailed results saved to: {output_dir.absolute()}")
@@ -37,9 +37,11 @@ class NodeDuplicateQuery(Query):
37
37
  super().__init__(**kwargs)
38
38
 
39
39
  def render_match(self) -> str:
40
+ labels_str = ":".join(self.previous_node.labels)
40
41
  query = f"""
41
42
  // Find all the active nodes
42
- MATCH (node:{self.previous_node.kind})
43
+ MATCH (node:{labels_str})
44
+ WITH DISTINCT node
43
45
  """
44
46
 
45
47
  return query
@@ -145,6 +147,7 @@ class NodeDuplicateQuery(Query):
145
147
  WITH active_node, new_node
146
148
  // Process Outbound Relationship
147
149
  MATCH (active_node)-[]->(peer)
150
+ WITH DISTINCT active_node, new_node, peer
148
151
  CALL (active_node, peer) {
149
152
  MATCH (active_node)-[r]->(peer)
150
153
  WHERE %(branch_filter)s
@@ -164,6 +167,7 @@ class NodeDuplicateQuery(Query):
164
167
  WITH DISTINCT active_node, new_node
165
168
  // Process Inbound Relationship
166
169
  MATCH (active_node)<-[]-(peer)
170
+ WITH DISTINCT active_node, new_node, peer
167
171
  CALL (active_node, peer) {
168
172
  MATCH (active_node)<-[r]-(peer)
169
173
  WHERE %(branch_filter)s
@@ -148,7 +148,14 @@ CALL (diff_path) {
148
148
  OR type(base_r_node) <> "IS_RELATED" OR type(base_r_prop) <> "IS_RELATED"
149
149
  )
150
150
  WITH latest_base_path, base_r_root, base_r_node, base_r_prop
151
- ORDER BY base_r_prop.from DESC, base_r_node.from DESC, base_r_root.from DESC
151
+ // status="active" ordering is for tie-breaking edges added and deleted at the same time, we want the active one
152
+ ORDER BY
153
+ base_r_prop.from DESC,
154
+ base_r_prop.status = "active" DESC,
155
+ base_r_node.from DESC,
156
+ base_r_node.status = "active" DESC,
157
+ base_r_root.from DESC,
158
+ base_r_root.status = "active" DESC
152
159
  LIMIT 1
153
160
  RETURN latest_base_path
154
161
  }
@@ -172,8 +179,6 @@ CALL (penultimate_path) {
172
179
  AND %(id_func)s(peer_r_node) = %(id_func)s(r_node)
173
180
  AND [%(id_func)s(n), type(peer_r_node)] <> [%(id_func)s(peer), type(r_peer)]
174
181
  AND r_peer.from < $to_time
175
- // filter out paths where an earlier from time follows a later from time
176
- AND peer_r_node.from <= r_peer.from
177
182
  // filter out paths where a base branch edge follows a branch edge
178
183
  AND (peer_r_node.branch = $base_branch_name OR r_peer.branch = $branch_name)
179
184
  // filter out paths where an active edge follows a deleted edge
@@ -663,6 +668,15 @@ AND ALL(
663
668
  AND ((r_pair[0]).status = "active" OR (r_pair[1]).status = "deleted")
664
669
  // filter out paths where an earlier from time follows a later from time
665
670
  AND (r_pair[0]).from <= (r_pair[1]).from
671
+ // if both are deleted, then the deeper edge must have been deleted first
672
+ AND ((r_pair[0]).status = "active" OR (r_pair[1]).status = "active" OR (r_pair[0]).from >= (r_pair[1].from))
673
+ AND (
674
+ (r_pair[0]).status = (r_pair[1]).status
675
+ OR (
676
+ (r_pair[0]).from <= (r_pair[1]).from
677
+ AND ((r_pair[0]).to IS NULL OR (r_pair[0]).to >= (r_pair[1]).from)
678
+ )
679
+ )
666
680
  // require adjacent edge pairs to have overlapping times, but only if on the same branch
667
681
  AND (
668
682
  (r_pair[0]).branch <> (r_pair[1]).branch
@@ -643,12 +643,9 @@ class RelationshipGetPeerQuery(Query):
643
643
 
644
644
  arrows = self.schema.get_query_arrows()
645
645
 
646
- path_str = (
647
- f"{arrows.left.start}[:IS_RELATED]{arrows.left.end}(rl){arrows.right.start}[:IS_RELATED]{arrows.right.end}"
648
- )
646
+ path_str = f"{arrows.left.start}[r1:IS_RELATED]{arrows.left.end}(rl){arrows.right.start}[r2:IS_RELATED]{arrows.right.end}"
649
647
 
650
648
  branch_level_str = "reduce(br_lvl = 0, r in relationships(path) | br_lvl + r.branch_level)"
651
- froms_str = db.render_list_comprehension(items="relationships(path)", item_name="from")
652
649
  query = """
653
650
  MATCH (source_node:Node)%(arrow_left_start)s[:IS_RELATED]%(arrow_left_end)s(rl:Relationship { name: $rel_identifier })
654
651
  WHERE source_node.uuid IN $source_ids
@@ -659,24 +656,24 @@ class RelationshipGetPeerQuery(Query):
659
656
  $source_kind IN LABELS(source_node) AND
660
657
  peer.uuid <> source_node.uuid AND
661
658
  $peer_kind IN LABELS(peer) AND
662
- all(r IN relationships(path) WHERE (%(branch_filter)s))
663
- WITH source_node, peer, rl, relationships(path) as rels, %(branch_level)s AS branch_level, %(froms)s AS froms
664
- RETURN peer as peer, rels, rl as rl1
665
- ORDER BY branch_level DESC, froms[-1] DESC, froms[-2] DESC
659
+ all(r IN [r1, r2] WHERE (%(branch_filter)s))
660
+ WITH source_node, peer, rl, r1, r2, %(branch_level)s AS branch_level
661
+ RETURN peer as peer, r1.status = "active" AND r2.status = "active" AS is_active, [r1, r2] AS rels
662
+ // status is required as a tiebreaker for migrated-kind nodes
663
+ ORDER BY branch_level DESC, r2.from DESC, r2.status ASC, r1.from DESC, r1.status ASC
666
664
  LIMIT 1
667
665
  }
668
- WITH peer, rl1 as rl, rels, source_node
666
+ WITH peer, rl, is_active, rels, source_node
669
667
  """ % {
670
668
  "path": path_str,
671
669
  "branch_filter": branch_filter,
672
670
  "branch_level": branch_level_str,
673
- "froms": froms_str,
674
671
  "arrow_left_start": arrows.left.start,
675
672
  "arrow_left_end": arrows.left.end,
676
673
  }
677
674
 
678
675
  self.add_to_query(query)
679
- where_clause = ['all(r IN rels WHERE r.status = "active")']
676
+ where_clause = ["is_active = TRUE"]
680
677
  clean_filters = extract_field_filters(field_name=self.schema.name, filters=self.filters)
681
678
 
682
679
  if (clean_filters and "id" in clean_filters) or "ids" in clean_filters:
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import copy
4
4
  import hashlib
5
+ import keyword
5
6
  from collections import defaultdict
6
7
  from itertools import chain, combinations
7
8
  from typing import Any
@@ -518,6 +519,7 @@ class SchemaBranch:
518
519
 
519
520
  def process_validate(self) -> None:
520
521
  self.validate_names()
522
+ self.validate_python_keywords()
521
523
  self.validate_kinds()
522
524
  self.validate_computed_attributes()
523
525
  self.validate_attribute_parameters()
@@ -987,6 +989,26 @@ class SchemaBranch:
987
989
  ):
988
990
  raise ValueError(f"{node.kind}: {rel.name} isn't allowed as a relationship name.")
989
991
 
992
+ def validate_python_keywords(self) -> None:
993
+ """Validate that attribute and relationship names don't use Python keywords."""
994
+ for name in self.all_names:
995
+ node = self.get(name=name, duplicate=False)
996
+
997
+ # Check for Python keywords in attribute names
998
+ for attribute in node.attributes:
999
+ if keyword.iskeyword(attribute.name):
1000
+ raise ValueError(
1001
+ f"Python keyword '{attribute.name}' cannot be used as an attribute name on '{node.kind}'"
1002
+ )
1003
+
1004
+ # Check for Python keywords in relationship names
1005
+ if config.SETTINGS.main.schema_strict_mode:
1006
+ for relationship in node.relationships:
1007
+ if keyword.iskeyword(relationship.name):
1008
+ raise ValueError(
1009
+ f"Python keyword '{relationship.name}' cannot be used as a relationship name on '{node.kind}' when using strict mode"
1010
+ )
1011
+
990
1012
  def _validate_common_parent(self, node: NodeSchema, rel: RelationshipSchema) -> None:
991
1013
  if not rel.common_parent:
992
1014
  return
@@ -214,7 +214,7 @@ async def request_generator_definition_run(
214
214
  repository_kind=repository.typename,
215
215
  branch_name=model.branch,
216
216
  query=model.generator_definition.query_name,
217
- variables=member.extract(params=model.generator_definition.parameters),
217
+ variables=await member.extract(params=model.generator_definition.parameters),
218
218
  target_id=member.id,
219
219
  target_name=member.display_label,
220
220
  )
@@ -1294,7 +1294,7 @@ class InfrahubRepositoryIntegrator(InfrahubRepositoryBase):
1294
1294
  query: CoreGraphQLQuery,
1295
1295
  ) -> ArtifactGenerateResult:
1296
1296
  """It doesn't look like this is used anywhere today ... we should either remove it or refactor render_artifact below to use this."""
1297
- variables = target.extract(params=definition.parameters.value)
1297
+ variables = await target.extract(params=definition.parameters.value)
1298
1298
  response = await self.sdk.query_gql_query(
1299
1299
  name=query.name.value,
1300
1300
  variables=variables,
infrahub/git/tasks.py CHANGED
@@ -365,7 +365,7 @@ async def generate_request_artifact_definition(
365
365
  repository_kind=repository.get_kind(),
366
366
  branch_name=model.branch,
367
367
  query=query.name.value,
368
- variables=member.extract(params=artifact_definition.parameters.value),
368
+ variables=await member.extract(params=artifact_definition.parameters.value),
369
369
  target_id=member.id,
370
370
  target_name=member.display_label,
371
371
  target_kind=member.get_kind(),
@@ -583,7 +583,7 @@ async def trigger_repository_user_checks_definitions(
583
583
  branch_name=model.branch_name,
584
584
  check_definition_id=model.check_definition_id,
585
585
  proposed_change=model.proposed_change,
586
- variables=member.extract(params=definition.parameters.value),
586
+ variables=await member.extract(params=definition.parameters.value),
587
587
  branch_diff=model.branch_diff,
588
588
  timeout=definition.timeout.value,
589
589
  )
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import hashlib
3
4
  from dataclasses import dataclass, field
4
5
  from typing import TYPE_CHECKING, Any
5
6
 
@@ -152,7 +153,7 @@ class InfrahubMutationMixin:
152
153
  """
153
154
  schema_branch = db.schema.get_schema_branch(name=branch.name)
154
155
  lock_names = _get_kind_lock_names_on_object_mutation(
155
- kind=cls._meta.active_schema.kind, branch=branch, schema_branch=schema_branch
156
+ kind=cls._meta.active_schema.kind, branch=branch, schema_branch=schema_branch, data=data
156
157
  )
157
158
  if lock_names:
158
159
  async with InfrahubMultiLock(lock_registry=lock.registry, locks=lock_names):
@@ -216,7 +217,7 @@ class InfrahubMutationMixin:
216
217
 
217
218
  schema_branch = db.schema.get_schema_branch(name=branch.name)
218
219
  lock_names = _get_kind_lock_names_on_object_mutation(
219
- kind=cls._meta.active_schema.kind, branch=branch, schema_branch=schema_branch
220
+ kind=cls._meta.active_schema.kind, branch=branch, schema_branch=schema_branch, data=data
220
221
  )
221
222
 
222
223
  if db.is_transaction:
@@ -266,7 +267,6 @@ class InfrahubMutationMixin:
266
267
  obj = node or await NodeManager.find_object(
267
268
  db=db, kind=cls._meta.active_schema.kind, id=data.get("id"), hfid=data.get("hfid"), branch=branch
268
269
  )
269
-
270
270
  obj, result = await cls._call_mutate_update(info=info, data=data, db=db, branch=branch, obj=obj)
271
271
 
272
272
  return obj, result
@@ -517,15 +517,34 @@ def _should_kind_be_locked_on_any_branch(kind: str, schema_branch: SchemaBranch)
517
517
  return False
518
518
 
519
519
 
520
- def _get_kind_lock_names_on_object_mutation(kind: str, branch: Branch, schema_branch: SchemaBranch) -> list[str]:
520
+ def _hash(value: str) -> str:
521
+ # Do not use builtin `hash` for lock names as due to randomization results would differ between
522
+ # different processes.
523
+ return hashlib.sha256(value.encode()).hexdigest()
524
+
525
+
526
+ def _get_kind_lock_names_on_object_mutation(
527
+ kind: str, branch: Branch, schema_branch: SchemaBranch, data: InputObjectType
528
+ ) -> list[str]:
521
529
  """
522
530
  Return objects kind for which we want to avoid concurrent mutation (create/update). Except for some specific kinds,
523
531
  concurrent mutations are only allowed on non-main branch as objects validations will be performed at least when merging in main branch.
524
532
  """
525
533
 
526
- if not branch.is_default and not _should_kind_be_locked_on_any_branch(kind, schema_branch):
534
+ if not branch.is_default and not _should_kind_be_locked_on_any_branch(kind=kind, schema_branch=schema_branch):
527
535
  return []
528
536
 
537
+ if kind == InfrahubKind.GRAPHQLQUERYGROUP:
538
+ # Lock on name as well to improve performances
539
+ try:
540
+ name = data.name.value
541
+ return [build_object_lock_name(kind + "." + _hash(name))]
542
+ except AttributeError:
543
+ # We might reach here if we are updating a CoreGraphQLQueryGroup without updating the name,
544
+ # in which case we would not need to lock. This is not supposed to happen as current `update`
545
+ # logic first fetches the node with its name.
546
+ return []
547
+
529
548
  lock_kinds = _get_kinds_to_lock_on_object_mutation(kind, schema_branch)
530
549
  lock_names = [build_object_lock_name(kind) for kind in lock_kinds]
531
550
  return lock_names
@@ -652,7 +652,7 @@ async def validate_artifacts_generation(
652
652
  repository_kind=repository.kind,
653
653
  branch_name=model.source_branch,
654
654
  query=model.artifact_definition.query_name,
655
- variables=member.extract(params=artifact_definition.parameters.value),
655
+ variables=await member.extract(params=artifact_definition.parameters.value),
656
656
  target_id=member.id,
657
657
  target_kind=member.get_kind(),
658
658
  target_name=member.display_label,
@@ -913,7 +913,7 @@ async def request_generator_definition_check(
913
913
  repository_kind=repository.kind,
914
914
  branch_name=model.source_branch,
915
915
  query=model.generator_definition.query_name,
916
- variables=member.extract(params=model.generator_definition.parameters),
916
+ variables=await member.extract(params=model.generator_definition.parameters),
917
917
  target_id=member.id,
918
918
  target_name=member.display_label,
919
919
  validator_id=validator.id,
infrahub_sdk/node/node.py CHANGED
@@ -8,7 +8,7 @@ from ..constants import InfrahubClientMode
8
8
  from ..exceptions import FeatureNotSupportedError, NodeNotFoundError, ResourceNotDefinedError, SchemaNotFoundError
9
9
  from ..graphql import Mutation, Query
10
10
  from ..schema import GenericSchemaAPI, RelationshipCardinality, RelationshipKind
11
- from ..utils import compare_lists, generate_short_id, get_flat_value
11
+ from ..utils import compare_lists, generate_short_id
12
12
  from .attribute import Attribute
13
13
  from .constants import (
14
14
  ARTIFACT_DEFINITION_GENERATE_FEATURE_NOT_SUPPORTED_MESSAGE,
@@ -418,14 +418,6 @@ class InfrahubNodeBase:
418
418
 
419
419
  return data
420
420
 
421
- def extract(self, params: dict[str, str]) -> dict[str, Any]:
422
- """Extract some datapoints defined in a flat notation."""
423
- result: dict[str, Any] = {}
424
- for key, value in params.items():
425
- result[key] = get_flat_value(self, key=value)
426
-
427
- return result
428
-
429
421
  def __hash__(self) -> int:
430
422
  return hash(self.id)
431
423
 
@@ -1036,6 +1028,46 @@ class InfrahubNode(InfrahubNodeBase):
1036
1028
 
1037
1029
  raise ResourceNotDefinedError(message=f"The node doesn't have a cardinality=one relationship for {name}")
1038
1030
 
1031
+ async def get_flat_value(self, key: str, separator: str = "__") -> Any:
1032
+ """Query recursively a value defined in a flat notation (string), on a hierarchy of objects
1033
+
1034
+ Examples:
1035
+ name__value
1036
+ module.object.value
1037
+ """
1038
+ if separator not in key:
1039
+ return getattr(self, key)
1040
+
1041
+ first, remaining = key.split(separator, maxsplit=1)
1042
+
1043
+ if first in self._schema.attribute_names:
1044
+ attr = getattr(self, first)
1045
+ for part in remaining.split(separator):
1046
+ attr = getattr(attr, part)
1047
+ return attr
1048
+
1049
+ try:
1050
+ rel = self._schema.get_relationship(name=first)
1051
+ except ValueError as exc:
1052
+ raise ValueError(f"No attribute or relationship named '{first}' for '{self._schema.kind}'") from exc
1053
+
1054
+ if rel.cardinality != RelationshipCardinality.ONE:
1055
+ raise ValueError(
1056
+ f"Can only look up flat value for relationships of cardinality {RelationshipCardinality.ONE.value}"
1057
+ )
1058
+
1059
+ related_node: RelatedNode = getattr(self, first)
1060
+ await related_node.fetch()
1061
+ return await related_node.peer.get_flat_value(key=remaining, separator=separator)
1062
+
1063
+ async def extract(self, params: dict[str, str]) -> dict[str, Any]:
1064
+ """Extract some datapoints defined in a flat notation."""
1065
+ result: dict[str, Any] = {}
1066
+ for key, value in params.items():
1067
+ result[key] = await self.get_flat_value(key=value)
1068
+
1069
+ return result
1070
+
1039
1071
  def __dir__(self) -> Iterable[str]:
1040
1072
  base = list(super().__dir__())
1041
1073
  return sorted(
@@ -1622,6 +1654,46 @@ class InfrahubNodeSync(InfrahubNodeBase):
1622
1654
 
1623
1655
  raise ResourceNotDefinedError(message=f"The node doesn't have a cardinality=one relationship for {name}")
1624
1656
 
1657
+ def get_flat_value(self, key: str, separator: str = "__") -> Any:
1658
+ """Query recursively a value defined in a flat notation (string), on a hierarchy of objects
1659
+
1660
+ Examples:
1661
+ name__value
1662
+ module.object.value
1663
+ """
1664
+ if separator not in key:
1665
+ return getattr(self, key)
1666
+
1667
+ first, remaining = key.split(separator, maxsplit=1)
1668
+
1669
+ if first in self._schema.attribute_names:
1670
+ attr = getattr(self, first)
1671
+ for part in remaining.split(separator):
1672
+ attr = getattr(attr, part)
1673
+ return attr
1674
+
1675
+ try:
1676
+ rel = self._schema.get_relationship(name=first)
1677
+ except ValueError as exc:
1678
+ raise ValueError(f"No attribute or relationship named '{first}' for '{self._schema.kind}'") from exc
1679
+
1680
+ if rel.cardinality != RelationshipCardinality.ONE:
1681
+ raise ValueError(
1682
+ f"Can only look up flat value for relationships of cardinality {RelationshipCardinality.ONE.value}"
1683
+ )
1684
+
1685
+ related_node: RelatedNodeSync = getattr(self, first)
1686
+ related_node.fetch()
1687
+ return related_node.peer.get_flat_value(key=remaining, separator=separator)
1688
+
1689
+ def extract(self, params: dict[str, str]) -> dict[str, Any]:
1690
+ """Extract some datapoints defined in a flat notation."""
1691
+ result: dict[str, Any] = {}
1692
+ for key, value in params.items():
1693
+ result[key] = self.get_flat_value(key=value)
1694
+
1695
+ return result
1696
+
1625
1697
  def __dir__(self) -> Iterable[str]:
1626
1698
  base = list(super().__dir__())
1627
1699
  return sorted(
@@ -204,8 +204,6 @@ class CoreNodeBase(Protocol):
204
204
 
205
205
  def get_raw_graphql_data(self) -> dict | None: ...
206
206
 
207
- def extract(self, params: dict[str, str]) -> dict[str, Any]: ...
208
-
209
207
 
210
208
  @runtime_checkable
211
209
  class CoreNode(CoreNodeBase, Protocol):
@@ -22,6 +22,7 @@ ATTRIBUTE_KIND_MAP = {
22
22
  "List": "ListAttribute",
23
23
  "JSON": "JSONAttribute",
24
24
  "Any": "AnyAttribute",
25
+ "NumberPool": "Integer",
25
26
  }
26
27
 
27
28
  # The order of the classes in the list determines the order of the classes in the generated code
infrahub_sdk/utils.py CHANGED
@@ -190,23 +190,6 @@ def str_to_bool(value: str) -> bool:
190
190
  raise ValueError(f"{value} can not be converted into a boolean") from exc
191
191
 
192
192
 
193
- def get_flat_value(obj: Any, key: str, separator: str = "__") -> Any:
194
- """Query recursively an value defined in a flat notation (string), on a hierarchy of objects
195
-
196
- Examples:
197
- name__value
198
- module.object.value
199
- """
200
- if separator not in key:
201
- return getattr(obj, key)
202
-
203
- first_part, remaining_part = key.split(separator, maxsplit=1)
204
- sub_obj = getattr(obj, first_part)
205
- if not sub_obj:
206
- return None
207
- return get_flat_value(obj=sub_obj, key=remaining_part, separator=separator)
208
-
209
-
210
193
  def generate_request_filename(request: httpx.Request) -> str:
211
194
  """Return a filename for a request sent to the Infrahub API
212
195
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: infrahub-server
3
- Version: 1.3.4
3
+ Version: 1.3.5
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: Apache-2.0
6
6
  Author: OpsMill
@@ -38,7 +38,7 @@ infrahub/branch/triggers.py,sha256=4sywoEX79fY2NkaGe6tTHnmytf4k6gXDm2FJHkkRJOw,7
38
38
  infrahub/cli/__init__.py,sha256=zQjE9zMrwAmk_4qb5mbUgNi06g3HKvrPwQvJLQmv9JY,1814
39
39
  infrahub/cli/constants.py,sha256=CoCeTMnfsA3j7ArdLKLZK4VPxOM7ls17qpxGJmND0m8,129
40
40
  infrahub/cli/context.py,sha256=20CJj_D1VhigR9uhTDPHiVHnV7vzsgK8v-uLKs06kzA,398
41
- infrahub/cli/db.py,sha256=7EEgiqcTtnejeHPC-m5iD4dnmtA22P-JSzvZ9Tcb5ho,36070
41
+ infrahub/cli/db.py,sha256=43u7i1iBkuv_TJMix9H_yLt6erJOgs5p-CoQZaAPIak,37362
42
42
  infrahub/cli/events.py,sha256=nJmowQgTxRs6qaT41A71Ei9jm6qtYaL2amAT5TA1H_k,1726
43
43
  infrahub/cli/git_agent.py,sha256=ajT9-kdd3xLIysOPe8GqZyCDMkpNyhqfWjBg9HPWVcg,5240
44
44
  infrahub/cli/patch.py,sha256=ztOkWyo0l_Wo0WX10bvSqGZibKzowrwx82oi69cjwkY,6018
@@ -193,7 +193,7 @@ infrahub/core/migrations/query/__init__.py,sha256=JoWOUWlV6IzwxWxObsfCnAAKUOHJkE
193
193
  infrahub/core/migrations/query/attribute_add.py,sha256=LlhkIfVOR3TFSUJEV_4kU5JBKXsWwTsRiX1ySUPe4TU,3655
194
194
  infrahub/core/migrations/query/attribute_rename.py,sha256=onb9Nanht1Tz47JgneAcFsuhqqvPS6dvI2nNjRupLLo,6892
195
195
  infrahub/core/migrations/query/delete_element_in_schema.py,sha256=QYw2LIpJGQXBPOTm6w9gFdCltZRd-V_YUh5l9HmGthg,7402
196
- infrahub/core/migrations/query/node_duplicate.py,sha256=CXkGoa6Dqg4njdg8GSNQUwoDDnHgiOn2O45zU1vN9lE,8527
196
+ infrahub/core/migrations/query/node_duplicate.py,sha256=sW7jRFdKM_AAkd5lbfqxgNZVcEu_e_u1K8epmoAVgaM,8698
197
197
  infrahub/core/migrations/query/relationship_duplicate.py,sha256=hjUFjNqhaFc2tEg79BXR2xDr_4Wdmu9fVF02cTEICTk,7319
198
198
  infrahub/core/migrations/query/schema_attribute_update.py,sha256=fLclNEgoikO_ddlFEo1ts-dZwTXITA85kdJ00fXFxqo,3382
199
199
  infrahub/core/migrations/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -230,10 +230,10 @@ infrahub/core/query/__init__.py,sha256=2qIMaODLwJ6pK6BUd5vODTlA15Aecf5I8_-J44UlC
230
230
  infrahub/core/query/attribute.py,sha256=DzwbElgTaZs6-nBYGmnDpBr9n0lmUPK3p7eyI30Snh8,11783
231
231
  infrahub/core/query/branch.py,sha256=B3QEqpwbJrs_8juWQPaHrdwLNJR-1tSkvMuixCFFdt4,3680
232
232
  infrahub/core/query/delete.py,sha256=7tPP1qtNV6QGYtmgE1RKsuQ9oxENnMTVkttLvJ2PiKg,1927
233
- infrahub/core/query/diff.py,sha256=DOtPHIu45Yp8wvj8wp16me9E3AK7wVcVfzS2_LIZn2k,35952
233
+ infrahub/core/query/diff.py,sha256=Dc70L5u1wokt106g84QNFJdKhnTTCxmCgAGsBilCgEo,36514
234
234
  infrahub/core/query/ipam.py,sha256=0glfVQmcKqMvNyK4GU_zRl2O9pjl7JBeavyE8VC-De4,28234
235
235
  infrahub/core/query/node.py,sha256=Rq0jR8Pbs7rPkPMCXnwHFp5Dcl8iLpgrFl4UFRfJ5is,67646
236
- infrahub/core/query/relationship.py,sha256=B0nmXq12XPm-_caCEPq7TpARFwLR9__Io7Hffgm7bfM,47876
236
+ infrahub/core/query/relationship.py,sha256=KmS9zrcr-RViXxiITXOjq1t0s-AfsICHk3wyyirZBfA,47817
237
237
  infrahub/core/query/resource_manager.py,sha256=NpxHVayh-HleoRz-bk54z2_PuBHBdU7ng3pCqKWObbo,16584
238
238
  infrahub/core/query/standard_node.py,sha256=mPBXyqk4RzoWRUX4NoojoVi8zk-sJ03GmzmUaWqOgSI,4825
239
239
  infrahub/core/query/subquery.py,sha256=UE071w3wccdU_dtKLV-7mdeQ53DKXjPmNxDV0zd5Tpg,7588
@@ -294,7 +294,7 @@ infrahub/core/schema/manager.py,sha256=Vz6EJo8pDq9u5apRU7wgFMtcsCHDEt9BHwS0VRlct
294
294
  infrahub/core/schema/node_schema.py,sha256=ld_Wrqf-RsoEUVz_lKE0tcSf5n_oYZYtRI0lTqtd63o,6150
295
295
  infrahub/core/schema/profile_schema.py,sha256=cOPSOt5KLgQ0nbqrAN_o33hY_pUtrKmiwSbY_YpVolI,1092
296
296
  infrahub/core/schema/relationship_schema.py,sha256=R-1iC1d70bBW0vWhgJhDB0_J3tRpOqcJmmLzh39NuYs,8501
297
- infrahub/core/schema/schema_branch.py,sha256=j2g-2o846OaQ4F-1MHYna-7KJsHrBDr54l1ANH-hTKA,105070
297
+ infrahub/core/schema/schema_branch.py,sha256=Yms2QdNZxqWjtK2sEAgxfRMQmeLEXA16VyqyHErwXgE,106138
298
298
  infrahub/core/schema/schema_branch_computed.py,sha256=14UUsQJDLMHkYhg7QMqeLiTF3PO8c8rGa90ul3F2ZZo,10629
299
299
  infrahub/core/schema/template_schema.py,sha256=O-PBS9IRM4JX6PxeoyZKwqZ0u0SdQ2zxWMc01PJ2_EA,1084
300
300
  infrahub/core/task/__init__.py,sha256=Ied1NvKGJUDmff27z_-yWW8ArenHxGvSvQTaQyx1iHs,128
@@ -423,15 +423,15 @@ infrahub/events/validator_action.py,sha256=nQJH-RWcgr3-tzmIldvPmu5O7dUAmv1qQnuxx
423
423
  infrahub/exceptions.py,sha256=cbM-f_2U-5ZFVZ_MaaXgs64k4M7uJ7fqDU2iCRoWlYY,11861
424
424
  infrahub/generators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
425
425
  infrahub/generators/models.py,sha256=9qhSfsoG-uYux35HClAxSq7TRfkosqN3i_eQkeTokLs,1916
426
- infrahub/generators/tasks.py,sha256=2G03bs8C0zS7uyGwthq0t3HO1J-4cAOa6CaxLgsAWUE,9469
426
+ infrahub/generators/tasks.py,sha256=9K7r9yt2s9kSUfaENeTBEU8Sf-omVuOxLyz_N1DjzxE,9475
427
427
  infrahub/git/__init__.py,sha256=KeQ9U8UI5jDj6KB6j00Oal7MZmtOD9vKqVgiezG_EQA,281
428
428
  infrahub/git/base.py,sha256=pMkavzZn34j50exrOYBzvlRrW5aGoP5XdWPCg6lMmx4,38802
429
429
  infrahub/git/constants.py,sha256=XpzcAkXbsgXZgrXey74id1sXV8Q6EHb_4FNw7BndxyY,106
430
430
  infrahub/git/directory.py,sha256=fozxLXXJPweHG95yQwQkR5yy3sfTdmHiczCAJnsUX54,861
431
- infrahub/git/integrator.py,sha256=wXAz6ejiRk0tEX1wiChKyvB5872r19Qmtgsa71tcxls,62397
431
+ infrahub/git/integrator.py,sha256=Oh181VNRn-YkllULu8J_J6Vh8VD5BfGQYCriOgZdd_w,62403
432
432
  infrahub/git/models.py,sha256=ozk9alxQ8Ops1lw1g8iR3O7INuw1VPsEUr5Wceh9HQY,12152
433
433
  infrahub/git/repository.py,sha256=mjYeH3pKWRM3UuvcwRCWeE793FuPbSdY8VF1IYK-BxA,11603
434
- infrahub/git/tasks.py,sha256=AzeeYIzsFj1dT6cG-2RJ6A-pDEXe_r2R8da4wWQJ0j8,37333
434
+ infrahub/git/tasks.py,sha256=7NPJxmzOcDworKT-veRcSoL3nM_Lj27VGgdQp3TsYEg,37345
435
435
  infrahub/git/utils.py,sha256=xhWxlu_FbMqbrwanpPkex4hKRS_d2AFzlxI_6kVQllw,1741
436
436
  infrahub/git/worktree.py,sha256=8IYJWOBytKUWwhMmMVehR4ceeO9e13nV-mvn3iVEgZY,1727
437
437
  infrahub/git_credential/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -477,7 +477,7 @@ infrahub/graphql/mutations/diff_conflict.py,sha256=JngQfyKXCVlmtlqQ_VyabmrOEDOEK
477
477
  infrahub/graphql/mutations/generator.py,sha256=Ulw4whZm8Gc8lJjwfUFoFSsR0cOUliFKl87Oca4B9O0,3579
478
478
  infrahub/graphql/mutations/graphql_query.py,sha256=mp_O2byChneCihUrEAFEiIAgJ1gW9WrgtwPetUQmkJw,3562
479
479
  infrahub/graphql/mutations/ipam.py,sha256=wIN8OcTNCHVy32YgatWZi2Of-snFYBd4wlxOAJvE-AY,15961
480
- infrahub/graphql/mutations/main.py,sha256=DB7UvTPopMOGH2jX6SG-bX7NUi3aF4AKiu5UeM20zL4,20787
480
+ infrahub/graphql/mutations/main.py,sha256=eqUSbjcnDvigmIeLrPA0nyiVHCHdzqDocfbSx-q63lA,21626
481
481
  infrahub/graphql/mutations/menu.py,sha256=u2UbOA-TFDRcZRGFkgYTmpGxN2IAUgOvJXd7SnsufyI,3708
482
482
  infrahub/graphql/mutations/models.py,sha256=ilkSLr8OxVO9v3Ra_uDyUTJT9qPOmdPMqQbuWIydJMo,264
483
483
  infrahub/graphql/mutations/node_getter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -604,7 +604,7 @@ infrahub/proposed_change/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
604
604
  infrahub/proposed_change/branch_diff.py,sha256=Oerw3cHo51XPKwBsAmpO0T470Fg9mkpWViHVY51hToY,2303
605
605
  infrahub/proposed_change/constants.py,sha256=w8fPxKWJM1DzeClRd7Vr53hxkzl2Bq-rnXWfE2y3Bz0,1296
606
606
  infrahub/proposed_change/models.py,sha256=ivWJmEAihprKmwgaBGDJ4Koq4ETciE5GfDp86KHDnns,5892
607
- infrahub/proposed_change/tasks.py,sha256=YUdbLiF7qim1LBa7Z8O-W5MIp1_FCiuPOLnPqLHbb0c,61865
607
+ infrahub/proposed_change/tasks.py,sha256=WJuXXJ4zR3MNSpr9ko2hF8HvLU92g3cYWwxSS9h0P6o,61877
608
608
  infrahub/pytest_plugin.py,sha256=u3t0WgLMo9XmuQYeb28mccQ3xbnyv2Fv173YWl1zBiM,6678
609
609
  infrahub/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
610
610
  infrahub/schema/tasks.py,sha256=vEaWWksqrfwwCAIgPxscVU81W9PIxODX552Rtkte1Cs,947
@@ -725,7 +725,7 @@ infrahub_sdk/jinja2.py,sha256=lTfV9E_P5gApaX6RW9M8U8oixQi-0H3U8wcs8fdGVaU,1150
725
725
  infrahub_sdk/node/__init__.py,sha256=clAUZ9lNVPFguelR5Sg9PzklAZruTKEm2xk-BaO68l8,1262
726
726
  infrahub_sdk/node/attribute.py,sha256=oEY1qxip8ETEx9Q33NhSQo013zmzrmpVIFzSkEMUY8M,4547
727
727
  infrahub_sdk/node/constants.py,sha256=TJO4uxvv7sc3FjoLdQdV7Ccymqz8AqxDenARst8awb4,775
728
- infrahub_sdk/node/node.py,sha256=ygvNc4qPs2RNemrrBrIx8WKMmV50hmGmU0xrCuA3htQ,70742
728
+ infrahub_sdk/node/node.py,sha256=0EuD7N3KyjCK6RkZ48EY0t5LZ68wHrH_wa8PG0tUtZw,73473
729
729
  infrahub_sdk/node/parsers.py,sha256=sLDdT6neoYSZIjOCmq8Bgd0LK8FFoasjvJLuSz0whSU,543
730
730
  infrahub_sdk/node/property.py,sha256=8Mjkc8bp3kLlHyllwxDJlpJTuOA1ciMgY8mtH3dFVLM,728
731
731
  infrahub_sdk/node/related_node.py,sha256=fPMnZ83OZnnbimaPC14MdE3lR-kumAA6hbOhRlo1gms,10093
@@ -734,9 +734,9 @@ infrahub_sdk/object_store.py,sha256=d-EDnxPpw_7BsbjbGbH50rjt-1-Ojj2zNrhFansP5hA,
734
734
  infrahub_sdk/operation.py,sha256=hsbZSjLbLsqvjZg5R5x_bOxxlteXJAk0fQy3mLrZhn4,2730
735
735
  infrahub_sdk/playback.py,sha256=ubkY1LiW_wFwm4auerdQ0zFJcFJZ1SYQT6-d4bxzaLg,1906
736
736
  infrahub_sdk/protocols.py,sha256=lmjBSrmpc-7j9H7mn0DaLpJa8eD2gQk2oy0u2HvGLOk,24209
737
- infrahub_sdk/protocols_base.py,sha256=TfKj2RluvkJ4MedNoB56i_wRce3YP7jEwaBdyBWZZ5I,5686
737
+ infrahub_sdk/protocols_base.py,sha256=rw5gP9IEuV2e-DeFHMUoL43nVfxEeGmQKjoE3YZCV78,5616
738
738
  infrahub_sdk/protocols_generator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
739
- infrahub_sdk/protocols_generator/constants.py,sha256=wEqe9XGe1mTYBXSmJ8rjQs82dQ4jM50qb8uS2ZGcriI,791
739
+ infrahub_sdk/protocols_generator/constants.py,sha256=8y5L7aqxhez6_10Cl2zUfNlHJCCosIVnxrOPKrwNVEw,820
740
740
  infrahub_sdk/protocols_generator/generator.py,sha256=hhBxxMw0Pgbih6GiC81xjb9R9TBT8I4y-O2cIdcbChs,5264
741
741
  infrahub_sdk/protocols_generator/template.j2,sha256=cm2wsKXHXOiW7N_byxnE2vLnn8gHQ99rs56qVquTTDw,3722
742
742
  infrahub_sdk/pytest_plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -791,7 +791,7 @@ infrahub_sdk/transfer/importer/json.py,sha256=-Tlmg22TiBrEqXOSLMnUzlCFOZ2M0Q8lWy
791
791
  infrahub_sdk/transfer/schema_sorter.py,sha256=ZoBjJGFT-6jQoKOLaoOPMAWzs7vGOeo7x6zOOP4LNv0,1244
792
792
  infrahub_sdk/transforms.py,sha256=RLiB_CkM-JQSfyifChxxQVl2FrHKOGEf_YynSMKeFZU,2340
793
793
  infrahub_sdk/types.py,sha256=UeZ1rDp4eyH12ApTcUD9a1OOtCp3IL1YZUeeZ06qF-I,1726
794
- infrahub_sdk/utils.py,sha256=XxrjiOx1sGxciyyMbh7kQyYb5Q9xUTbQY2RjAMdUfXQ,12276
794
+ infrahub_sdk/utils.py,sha256=dkNqnMEzyPORQ6mw90mH3Qge1fkIclcuQ5kmxND1JAg,11748
795
795
  infrahub_sdk/uuidt.py,sha256=Tz-4nHkJwbi39UT3gaIe2wJeZNAoBqf6tm3sw7LZbXc,2155
796
796
  infrahub_sdk/yaml.py,sha256=PRsS7BEM-Xn5wRLAAG-YLTGRBEJy5Dnyim2YskFfe8I,5539
797
797
  infrahub_testcontainers/__init__.py,sha256=oPpmesGgYBSdKTg1L37FGwYBeao1EHury5SJGul-CT8,216
@@ -807,8 +807,8 @@ infrahub_testcontainers/models.py,sha256=ASYyvl7d_WQz_i7y8-3iab9hwwmCl3OCJavqVbe
807
807
  infrahub_testcontainers/performance_test.py,sha256=hvwiy6tc_lWniYqGkqfOXVGAmA_IV15VOZqbiD9ezno,6149
808
808
  infrahub_testcontainers/plugin.py,sha256=I3RuZQ0dARyKHuqCf0y1Yj731P2Mwf3BJUehRJKeWrs,5645
809
809
  infrahub_testcontainers/prometheus.yml,sha256=610xQEyj3xuVJMzPkC4m1fRnCrjGpiRBrXA2ytCLa54,599
810
- infrahub_server-1.3.4.dist-info/LICENSE.txt,sha256=7GQO7kxVoQYnZtFrjZBKLRXbrGwwwimHPPOJtqXsozQ,11340
811
- infrahub_server-1.3.4.dist-info/METADATA,sha256=5-atekQwfiYJP5jpARiSbt06s3MxNqiK2w0-5ZMRqQo,8189
812
- infrahub_server-1.3.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
813
- infrahub_server-1.3.4.dist-info/entry_points.txt,sha256=UXIeFWDsrV-4IllNvUEd6KieYGzQfn9paga2YyABOQI,393
814
- infrahub_server-1.3.4.dist-info/RECORD,,
810
+ infrahub_server-1.3.5.dist-info/LICENSE.txt,sha256=7GQO7kxVoQYnZtFrjZBKLRXbrGwwwimHPPOJtqXsozQ,11340
811
+ infrahub_server-1.3.5.dist-info/METADATA,sha256=VciuAufvS-mwMz8x9FC8ca1qiCbS7lR0xpoZsoeeZ1k,8189
812
+ infrahub_server-1.3.5.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
813
+ infrahub_server-1.3.5.dist-info/entry_points.txt,sha256=UXIeFWDsrV-4IllNvUEd6KieYGzQfn9paga2YyABOQI,393
814
+ infrahub_server-1.3.5.dist-info/RECORD,,