infrahub-server 1.7.0b0__py3-none-any.whl → 1.7.0rc0__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/api/exceptions.py +2 -2
- infrahub/cli/db.py +48 -22
- infrahub/core/account.py +12 -9
- infrahub/core/diff/branch_differ.py +1 -1
- infrahub/core/diff/conflict_transferer.py +1 -1
- infrahub/core/diff/data_check_synchronizer.py +1 -1
- infrahub/core/diff/enricher/cardinality_one.py +1 -1
- infrahub/core/diff/enricher/hierarchy.py +1 -1
- infrahub/core/diff/enricher/labels.py +1 -1
- infrahub/core/diff/merger/merger.py +1 -1
- infrahub/core/diff/repository/repository.py +3 -1
- infrahub/core/graph/constraints.py +1 -1
- infrahub/core/ipam/reconciler.py +8 -6
- infrahub/core/ipam/utilization.py +8 -15
- infrahub/core/manager.py +1 -26
- infrahub/core/merge.py +1 -1
- infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -12
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +4 -4
- infrahub/core/migrations/graph/m041_deleted_dup_edges.py +1 -1
- infrahub/core/migrations/graph/m049_remove_is_visible_relationship.py +16 -1
- infrahub/core/migrations/query/__init__.py +2 -2
- infrahub/core/migrations/query/schema_attribute_update.py +1 -1
- infrahub/core/migrations/schema/attribute_name_update.py +1 -1
- infrahub/core/migrations/schema/attribute_supports_profile.py +2 -2
- infrahub/core/migrations/schema/node_attribute_add.py +1 -1
- infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
- infrahub/core/migrations/schema/node_kind_update.py +1 -1
- infrahub/core/node/__init__.py +1 -1
- infrahub/core/node/base.py +9 -5
- infrahub/core/node/delete_validator.py +1 -1
- infrahub/core/order.py +30 -0
- infrahub/core/protocols.py +1 -0
- infrahub/core/protocols_base.py +4 -0
- infrahub/core/query/__init__.py +8 -5
- infrahub/core/query/attribute.py +3 -3
- infrahub/core/query/branch.py +1 -1
- infrahub/core/query/delete.py +1 -1
- infrahub/core/query/diff.py +3 -3
- infrahub/core/query/ipam.py +104 -43
- infrahub/core/query/node.py +454 -101
- infrahub/core/query/relationship.py +83 -26
- infrahub/core/query/resource_manager.py +107 -18
- infrahub/core/relationship/constraints/count.py +1 -1
- infrahub/core/relationship/constraints/peer_kind.py +1 -1
- infrahub/core/relationship/constraints/peer_parent.py +1 -1
- infrahub/core/relationship/constraints/peer_relatives.py +1 -1
- infrahub/core/relationship/constraints/profiles_kind.py +1 -1
- infrahub/core/relationship/constraints/profiles_removal.py +1 -1
- infrahub/core/schema/attribute_schema.py +0 -13
- infrahub/core/schema/basenode_schema.py +3 -0
- infrahub/core/schema/definitions/core/__init__.py +8 -2
- infrahub/core/schema/definitions/core/account.py +10 -10
- infrahub/core/schema/definitions/core/artifact.py +14 -8
- infrahub/core/schema/definitions/core/check.py +10 -4
- infrahub/core/schema/definitions/core/generator.py +26 -6
- infrahub/core/schema/definitions/core/graphql_query.py +1 -1
- infrahub/core/schema/definitions/core/group.py +9 -2
- infrahub/core/schema/definitions/core/ipam.py +80 -10
- infrahub/core/schema/definitions/core/menu.py +41 -7
- infrahub/core/schema/definitions/core/permission.py +16 -2
- infrahub/core/schema/definitions/core/profile.py +16 -2
- infrahub/core/schema/definitions/core/propose_change.py +24 -4
- infrahub/core/schema/definitions/core/propose_change_comment.py +23 -11
- infrahub/core/schema/definitions/core/propose_change_validator.py +50 -21
- infrahub/core/schema/definitions/core/repository.py +10 -0
- infrahub/core/schema/definitions/core/resource_pool.py +8 -1
- infrahub/core/schema/definitions/core/template.py +19 -2
- infrahub/core/schema/definitions/core/transform.py +11 -5
- infrahub/core/schema/definitions/core/webhook.py +27 -9
- infrahub/core/schema/schema_branch.py +68 -2
- infrahub/core/utils.py +3 -3
- infrahub/core/validators/aggregated_checker.py +1 -1
- infrahub/core/validators/attribute/choices.py +1 -1
- infrahub/core/validators/attribute/enum.py +1 -1
- infrahub/core/validators/attribute/kind.py +1 -1
- infrahub/core/validators/attribute/length.py +1 -1
- infrahub/core/validators/attribute/min_max.py +1 -1
- infrahub/core/validators/attribute/number_pool.py +1 -1
- infrahub/core/validators/attribute/optional.py +1 -1
- infrahub/core/validators/attribute/regex.py +1 -1
- infrahub/core/validators/node/attribute.py +1 -1
- infrahub/core/validators/node/relationship.py +1 -1
- infrahub/core/validators/relationship/peer.py +1 -1
- infrahub/database/__init__.py +1 -1
- infrahub/git/utils.py +1 -1
- infrahub/graphql/app.py +2 -2
- infrahub/graphql/field_extractor.py +1 -1
- infrahub/graphql/manager.py +9 -1
- infrahub/graphql/mutations/account.py +1 -1
- infrahub/graphql/order.py +14 -0
- infrahub/graphql/queries/diff/tree.py +5 -5
- infrahub/graphql/queries/resource_manager.py +25 -24
- infrahub/graphql/resolvers/ipam.py +3 -3
- infrahub/graphql/resolvers/resolver.py +44 -3
- infrahub/graphql/types/standard_node.py +8 -4
- infrahub/menu/repository.py +1 -1
- infrahub/patch/queries/base.py +1 -1
- infrahub/pools/number.py +1 -8
- infrahub/profiles/node_applier.py +1 -1
- infrahub/profiles/queries/get_profile_data.py +1 -1
- infrahub/proposed_change/action_checker.py +1 -1
- infrahub/services/__init__.py +1 -1
- infrahub/services/adapters/cache/nats.py +1 -1
- infrahub/webhook/gather.py +1 -1
- infrahub/webhook/tasks.py +22 -6
- {infrahub_server-1.7.0b0.dist-info → infrahub_server-1.7.0rc0.dist-info}/METADATA +1 -1
- {infrahub_server-1.7.0b0.dist-info → infrahub_server-1.7.0rc0.dist-info}/RECORD +111 -110
- infrahub_testcontainers/models.py +3 -3
- infrahub/graphql/models.py +0 -36
- {infrahub_server-1.7.0b0.dist-info → infrahub_server-1.7.0rc0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.7.0b0.dist-info → infrahub_server-1.7.0rc0.dist-info}/entry_points.txt +0 -0
- {infrahub_server-1.7.0b0.dist-info → infrahub_server-1.7.0rc0.dist-info}/licenses/LICENSE.txt +0 -0
infrahub/core/query/ipam.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, Iterable
|
|
|
7
7
|
from infrahub.core.constants import InfrahubKind
|
|
8
8
|
from infrahub.core.graph.schema import GraphAttributeIPHostNode, GraphAttributeIPNetworkNode
|
|
9
9
|
from infrahub.core.ipam.constants import AllIPTypes, IPAddressType, IPNetworkType
|
|
10
|
-
from infrahub.core.query import QueryType
|
|
10
|
+
from infrahub.core.query import QueryResult, QueryType
|
|
11
11
|
from infrahub.core.registry import registry
|
|
12
12
|
from infrahub.core.utils import convert_ip_to_binary_str
|
|
13
13
|
|
|
@@ -57,7 +57,7 @@ class IPPrefixSubnetFetch(Query):
|
|
|
57
57
|
obj: IPNetworkType,
|
|
58
58
|
namespace: Node | str | None = None,
|
|
59
59
|
**kwargs,
|
|
60
|
-
):
|
|
60
|
+
) -> None:
|
|
61
61
|
self.obj = obj
|
|
62
62
|
self.namespace_id = _get_namespace_id(namespace)
|
|
63
63
|
|
|
@@ -146,7 +146,7 @@ class IPPrefixIPAddressFetch(Query):
|
|
|
146
146
|
obj: IPNetworkType,
|
|
147
147
|
namespace: Node | str | None = None,
|
|
148
148
|
**kwargs,
|
|
149
|
-
):
|
|
149
|
+
) -> None:
|
|
150
150
|
self.obj = obj
|
|
151
151
|
self.namespace_id = _get_namespace_id(namespace)
|
|
152
152
|
|
|
@@ -242,11 +242,53 @@ async def get_ip_addresses(
|
|
|
242
242
|
return query.get_addresses()
|
|
243
243
|
|
|
244
244
|
|
|
245
|
+
@dataclass(frozen=True)
|
|
246
|
+
class IPPrefixUtilizationResult:
|
|
247
|
+
"""Result from IPPrefixUtilization containing prefix child allocation data."""
|
|
248
|
+
|
|
249
|
+
prefix_uuid: str
|
|
250
|
+
"""UUID of the parent prefix node."""
|
|
251
|
+
|
|
252
|
+
child_uuid: str
|
|
253
|
+
"""UUID of the child node (prefix or address)."""
|
|
254
|
+
|
|
255
|
+
child_kind: str
|
|
256
|
+
"""Kind/type of the child node."""
|
|
257
|
+
|
|
258
|
+
child_labels: tuple[str, ...]
|
|
259
|
+
"""Labels of the child node (used to determine if IPADDRESS or IPPREFIX)."""
|
|
260
|
+
|
|
261
|
+
ip_value: str
|
|
262
|
+
"""IP value (address or prefix) of the child."""
|
|
263
|
+
|
|
264
|
+
prefixlen: int
|
|
265
|
+
"""Prefix length of the child IP value."""
|
|
266
|
+
|
|
267
|
+
branch: str
|
|
268
|
+
"""Branch name where this allocation exists."""
|
|
269
|
+
|
|
270
|
+
@classmethod
|
|
271
|
+
def from_db(cls, result: QueryResult) -> IPPrefixUtilizationResult:
|
|
272
|
+
"""Convert raw QueryResult to typed dataclass."""
|
|
273
|
+
pfx = result.get_node("pfx")
|
|
274
|
+
child = result.get_node("child")
|
|
275
|
+
av = result.get_node("av")
|
|
276
|
+
return cls(
|
|
277
|
+
prefix_uuid=str(pfx.get("uuid")),
|
|
278
|
+
child_uuid=str(child.get("uuid")),
|
|
279
|
+
child_kind=child.get("kind"),
|
|
280
|
+
child_labels=tuple(child.labels),
|
|
281
|
+
ip_value=av.get("value"),
|
|
282
|
+
prefixlen=av.get("prefixlen"),
|
|
283
|
+
branch=str(result.get("branch")),
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
|
|
245
287
|
class IPPrefixUtilization(Query):
|
|
246
288
|
name = "ipprefix_utilization_prefix"
|
|
247
289
|
type = QueryType.READ
|
|
248
290
|
|
|
249
|
-
def __init__(self, ip_prefixes: list[str], allocated_kinds: list[str], **kwargs):
|
|
291
|
+
def __init__(self, ip_prefixes: list[str], allocated_kinds: list[str], **kwargs) -> None:
|
|
250
292
|
self.ip_prefixes = ip_prefixes
|
|
251
293
|
self.allocated_kinds: list[str] = []
|
|
252
294
|
self.allocated_kinds_rel: list[str] = []
|
|
@@ -315,6 +357,55 @@ class IPPrefixUtilization(Query):
|
|
|
315
357
|
self.return_labels = ["pfx", "child", "av", "branch_level", "branch"]
|
|
316
358
|
self.add_to_query(query)
|
|
317
359
|
|
|
360
|
+
def get_data(self) -> list[IPPrefixUtilizationResult]:
|
|
361
|
+
"""Return results as typed dataclass instances.
|
|
362
|
+
|
|
363
|
+
Returns:
|
|
364
|
+
List of IPPrefixUtilizationResult containing prefix child allocation data.
|
|
365
|
+
"""
|
|
366
|
+
return [IPPrefixUtilizationResult.from_db(result) for result in self.get_results()]
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
@dataclass(frozen=True)
|
|
370
|
+
class IPPrefixReconcileQueryResult:
|
|
371
|
+
"""Result from IPPrefixReconcileQuery containing IP reconciliation data."""
|
|
372
|
+
|
|
373
|
+
ip_node_uuid: str | None
|
|
374
|
+
"""UUID of the IP node being reconciled, or None if not found."""
|
|
375
|
+
|
|
376
|
+
current_parent_uuid: str | None
|
|
377
|
+
"""UUID of the current parent prefix, or None if no parent exists."""
|
|
378
|
+
|
|
379
|
+
calculated_parent_uuid: str | None
|
|
380
|
+
"""UUID of the calculated correct parent prefix, or None if should be top-level."""
|
|
381
|
+
|
|
382
|
+
current_children_uuids: tuple[str, ...]
|
|
383
|
+
"""UUIDs of current child prefixes/addresses."""
|
|
384
|
+
|
|
385
|
+
calculated_children_uuids: tuple[str, ...]
|
|
386
|
+
"""UUIDs of calculated correct child prefixes/addresses."""
|
|
387
|
+
|
|
388
|
+
@classmethod
|
|
389
|
+
def from_db(cls, result: QueryResult) -> IPPrefixReconcileQueryResult:
|
|
390
|
+
"""Convert raw QueryResult to typed dataclass."""
|
|
391
|
+
|
|
392
|
+
def get_optional_node_uuid(label: str) -> str | None:
|
|
393
|
+
"""Extract UUID from an optional node (may be None from OPTIONAL MATCH)."""
|
|
394
|
+
node = result.get(label)
|
|
395
|
+
return str(node.get("uuid")) if node and node.get("uuid") else None
|
|
396
|
+
|
|
397
|
+
def get_collection_uuids(label: str) -> tuple[str, ...]:
|
|
398
|
+
"""Extract UUIDs from a node collection (may contain None from COLLECT)."""
|
|
399
|
+
return tuple(str(n.get("uuid")) for n in result.get_node_collection(label) if n and n.get("uuid"))
|
|
400
|
+
|
|
401
|
+
return cls(
|
|
402
|
+
ip_node_uuid=get_optional_node_uuid("ip_node"),
|
|
403
|
+
current_parent_uuid=get_optional_node_uuid("current_parent"),
|
|
404
|
+
calculated_parent_uuid=get_optional_node_uuid("new_parent"),
|
|
405
|
+
current_children_uuids=get_collection_uuids("current_children"),
|
|
406
|
+
calculated_children_uuids=get_collection_uuids("new_children"),
|
|
407
|
+
)
|
|
408
|
+
|
|
318
409
|
|
|
319
410
|
class IPPrefixReconcileQuery(Query):
|
|
320
411
|
name = "ip_prefix_reconcile"
|
|
@@ -326,7 +417,7 @@ class IPPrefixReconcileQuery(Query):
|
|
|
326
417
|
namespace: Node | str | None = None,
|
|
327
418
|
node_uuid: str | None = None,
|
|
328
419
|
**kwargs,
|
|
329
|
-
):
|
|
420
|
+
) -> None:
|
|
330
421
|
self.ip_value = ip_value
|
|
331
422
|
self.ip_uuid = node_uuid
|
|
332
423
|
self.namespace_id = _get_namespace_id(namespace)
|
|
@@ -702,44 +793,14 @@ class IPPrefixReconcileQuery(Query):
|
|
|
702
793
|
self.order_by = ["ip_node.uuid"]
|
|
703
794
|
self.return_labels = ["ip_node", "current_parent", "current_children", "new_parent", "new_children"]
|
|
704
795
|
|
|
705
|
-
def
|
|
706
|
-
|
|
707
|
-
if not results:
|
|
708
|
-
return None
|
|
709
|
-
result = results[0]
|
|
710
|
-
node = result.get(node_name)
|
|
711
|
-
if not node:
|
|
712
|
-
return None
|
|
713
|
-
node_uuid = node.get("uuid")
|
|
714
|
-
if node_uuid:
|
|
715
|
-
return str(node_uuid)
|
|
716
|
-
return None
|
|
796
|
+
def get_data(self) -> IPPrefixReconcileQueryResult | None:
|
|
797
|
+
"""Return single result as typed dataclass instance.
|
|
717
798
|
|
|
718
|
-
|
|
799
|
+
Returns:
|
|
800
|
+
IPPrefixReconcileQueryResult containing reconciliation data,
|
|
801
|
+
or None if no results found.
|
|
802
|
+
"""
|
|
719
803
|
results = list(self.get_results())
|
|
720
804
|
if not results:
|
|
721
|
-
return
|
|
722
|
-
|
|
723
|
-
element_uuids = []
|
|
724
|
-
for element in result.get(alias_name):
|
|
725
|
-
if not element:
|
|
726
|
-
continue
|
|
727
|
-
element_uuid = element.get("uuid")
|
|
728
|
-
if element_uuid:
|
|
729
|
-
element_uuids.append(str(element_uuid))
|
|
730
|
-
return element_uuids
|
|
731
|
-
|
|
732
|
-
def get_ip_node_uuid(self) -> str | None:
|
|
733
|
-
return self._get_uuid_from_query("ip_node")
|
|
734
|
-
|
|
735
|
-
def get_current_parent_uuid(self) -> str | None:
|
|
736
|
-
return self._get_uuid_from_query("current_parent")
|
|
737
|
-
|
|
738
|
-
def get_calculated_parent_uuid(self) -> str | None:
|
|
739
|
-
return self._get_uuid_from_query("new_parent")
|
|
740
|
-
|
|
741
|
-
def get_current_children_uuids(self) -> list[str]:
|
|
742
|
-
return self._get_uuids_from_query_list("current_children")
|
|
743
|
-
|
|
744
|
-
def get_calculated_children_uuids(self) -> list[str]:
|
|
745
|
-
return self._get_uuids_from_query_list("new_children")
|
|
805
|
+
return None
|
|
806
|
+
return IPPrefixReconcileQueryResult.from_db(results[0])
|