infrahub-server 1.4.4__py3-none-any.whl → 1.4.6__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/actions/constants.py +6 -0
- infrahub/api/query.py +2 -2
- infrahub/core/account.py +60 -34
- infrahub/core/query/ipam.py +150 -50
- infrahub/generators/tasks.py +9 -6
- infrahub/git/tasks.py +9 -6
- infrahub/proposed_change/tasks.py +16 -10
- {infrahub_server-1.4.4.dist-info → infrahub_server-1.4.6.dist-info}/METADATA +1 -1
- {infrahub_server-1.4.4.dist-info → infrahub_server-1.4.6.dist-info}/RECORD +12 -12
- {infrahub_server-1.4.4.dist-info → infrahub_server-1.4.6.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.4.4.dist-info → infrahub_server-1.4.6.dist-info}/WHEEL +0 -0
- {infrahub_server-1.4.4.dist-info → infrahub_server-1.4.6.dist-info}/entry_points.txt +0 -0
infrahub/actions/constants.py
CHANGED
|
@@ -118,6 +118,12 @@ class ValueMatch(DropdownEnum):
|
|
|
118
118
|
description="Match against both the current and previous values",
|
|
119
119
|
color="#5ac8fa",
|
|
120
120
|
)
|
|
121
|
+
ANY = DropdownChoice(
|
|
122
|
+
name="any",
|
|
123
|
+
label="Any",
|
|
124
|
+
description="Match against any value",
|
|
125
|
+
color="#276cc2",
|
|
126
|
+
)
|
|
121
127
|
|
|
122
128
|
|
|
123
129
|
NODES_THAT_TRIGGER_ACTION_RULES_SETUP = [
|
infrahub/api/query.py
CHANGED
|
@@ -40,7 +40,7 @@ router = APIRouter(prefix="/query")
|
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
class QueryPayload(BaseModel):
|
|
43
|
-
variables: dict[str,
|
|
43
|
+
variables: dict[str, Any] = Field(default_factory=dict)
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
async def execute_query(
|
|
@@ -48,7 +48,7 @@ async def execute_query(
|
|
|
48
48
|
request: Request,
|
|
49
49
|
branch_params: BranchParams,
|
|
50
50
|
query_id: str,
|
|
51
|
-
params: dict[str,
|
|
51
|
+
params: dict[str, Any],
|
|
52
52
|
update_group: bool,
|
|
53
53
|
subscribers: list[str],
|
|
54
54
|
permission_checker: GraphQLQueryPermissionChecker,
|
infrahub/core/account.py
CHANGED
|
@@ -5,9 +5,10 @@ from typing import TYPE_CHECKING, Any
|
|
|
5
5
|
|
|
6
6
|
from typing_extensions import Self
|
|
7
7
|
|
|
8
|
-
from infrahub.core.constants import InfrahubKind, PermissionDecision
|
|
8
|
+
from infrahub.core.constants import NULL_VALUE, InfrahubKind, PermissionDecision
|
|
9
9
|
from infrahub.core.query import Query, QueryType
|
|
10
10
|
from infrahub.core.registry import registry
|
|
11
|
+
from infrahub.core.timestamp import Timestamp
|
|
11
12
|
|
|
12
13
|
if TYPE_CHECKING:
|
|
13
14
|
from infrahub.core.branch import Branch
|
|
@@ -519,47 +520,72 @@ class AccountTokenValidateQuery(Query):
|
|
|
519
520
|
super().__init__(**kwargs)
|
|
520
521
|
|
|
521
522
|
async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
|
|
522
|
-
|
|
523
|
-
|
|
523
|
+
branch_filter, branch_params = self.branch.get_query_filter_path(
|
|
524
|
+
at=self.at.to_string(), branch_agnostic=self.branch_agnostic, is_isolated=False
|
|
524
525
|
)
|
|
525
|
-
self.params.update(
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
526
|
+
self.params.update(branch_params)
|
|
527
|
+
self.params.update(
|
|
528
|
+
{
|
|
529
|
+
"token_attr_name": "token",
|
|
530
|
+
"token_relationship_name": "account__token",
|
|
531
|
+
"token_value": self.token,
|
|
532
|
+
"null_value": NULL_VALUE,
|
|
533
|
+
}
|
|
529
534
|
)
|
|
530
|
-
self.params.update(account_params)
|
|
531
535
|
|
|
532
|
-
self.params["token_value"] = self.token
|
|
533
|
-
|
|
534
|
-
# ruff: noqa: E501
|
|
535
536
|
query = """
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
537
|
+
// --------------
|
|
538
|
+
// get the active token node for this token value, if it exists
|
|
539
|
+
// --------------
|
|
540
|
+
MATCH (token_node:%(token_node_kind)s)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: $token_attr_name})
|
|
541
|
+
-[r2:HAS_VALUE]->(av:AttributeValueIndexed { value: $token_value })
|
|
542
|
+
WHERE all(r in [r1, r2] WHERE (%(branch_filter)s))
|
|
543
|
+
ORDER BY r1.branch_level DESC, r1.from DESC, r1.status ASC, r2.branch_level DESC, r2.from DESC, r2.status ASC
|
|
544
|
+
LIMIT 1
|
|
545
|
+
WITH token_node
|
|
546
|
+
WHERE r1.status = "active" AND r2.status = "active"
|
|
547
|
+
// --------------
|
|
548
|
+
// get the expiration time
|
|
549
|
+
// --------------
|
|
550
|
+
OPTIONAL MATCH (token_node)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "expiration"})
|
|
551
|
+
-[r2:HAS_VALUE]->(av)
|
|
552
|
+
WHERE all(r in [r1, r2] WHERE (%(branch_filter)s))
|
|
553
|
+
ORDER BY r1.branch_level DESC, r1.from DESC, r1.status ASC, r2.branch_level DESC, r2.from DESC, r2.status ASC
|
|
554
|
+
LIMIT 1
|
|
555
|
+
WITH token_node, CASE
|
|
556
|
+
WHEN r1.status = "active" AND r2.status = "active" AND av.value <> $null_value THEN av.value
|
|
557
|
+
ELSE NULL
|
|
558
|
+
END AS expiration
|
|
559
|
+
// --------------
|
|
560
|
+
// get the linked account node from the token node
|
|
561
|
+
// --------------
|
|
562
|
+
MATCH (token_node)-[r1:IS_RELATED]-(:Relationship {name: $token_relationship_name})-[r2:IS_RELATED]-(account_node:%(account_node_kind)s)
|
|
563
|
+
WHERE all(r in [r1, r2] WHERE (%(branch_filter)s))
|
|
564
|
+
ORDER BY r1.branch_level DESC, r1.from DESC, r1.status ASC, r2.branch_level DESC, r2.from DESC, r2.status ASC
|
|
565
|
+
LIMIT 1
|
|
566
|
+
WITH expiration, account_node
|
|
567
|
+
WHERE r1.status = "active" AND r2.status = "active"
|
|
568
|
+
""" % {
|
|
569
|
+
"branch_filter": branch_filter,
|
|
570
|
+
"token_node_kind": InfrahubKind.ACCOUNTTOKEN,
|
|
571
|
+
"account_node_kind": InfrahubKind.GENERICACCOUNT,
|
|
572
|
+
}
|
|
546
573
|
self.add_to_query(query)
|
|
547
|
-
|
|
548
|
-
self.return_labels = ["at", "av", "acc"]
|
|
549
|
-
|
|
550
|
-
def get_account_name(self) -> str | None:
|
|
551
|
-
"""Return the account name that matched the query or None."""
|
|
552
|
-
if result := self.get_result():
|
|
553
|
-
return result.get("av").get("value")
|
|
554
|
-
|
|
555
|
-
return None
|
|
574
|
+
self.return_labels = ["account_node.uuid AS account_uuid", "expiration"]
|
|
556
575
|
|
|
557
576
|
def get_account_id(self) -> str | None:
|
|
558
577
|
"""Return the account id that matched the query or a None."""
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
578
|
+
result = self.get_result()
|
|
579
|
+
if not result:
|
|
580
|
+
return None
|
|
581
|
+
account_uuid = result.get_as_str(label="account_uuid")
|
|
582
|
+
expiration_with_tz = result.get_as_str(label="expiration")
|
|
583
|
+
if expiration_with_tz is None:
|
|
584
|
+
return account_uuid
|
|
585
|
+
expiration = Timestamp(expiration_with_tz)
|
|
586
|
+
if expiration < Timestamp():
|
|
587
|
+
return None
|
|
588
|
+
return account_uuid
|
|
563
589
|
|
|
564
590
|
|
|
565
591
|
async def validate_token(token: str, db: InfrahubDatabase, branch: Branch | str | None = None) -> str | None:
|
infrahub/core/query/ipam.py
CHANGED
|
@@ -375,6 +375,10 @@ class IPPrefixReconcileQuery(Query):
|
|
|
375
375
|
// ------------------
|
|
376
376
|
MATCH (ip_namespace:%(namespace_kind)s {uuid: $namespace_id})-[r:IS_PART_OF]->(root:Root)
|
|
377
377
|
WHERE %(branch_filter)s
|
|
378
|
+
ORDER BY r.branch_level DESC, r.from DESC, r.status ASC
|
|
379
|
+
LIMIT 1
|
|
380
|
+
WITH ip_namespace
|
|
381
|
+
WHERE r.status = "active"
|
|
378
382
|
""" % {"branch_filter": branch_filter, "namespace_kind": self.params["namespace_kind"]}
|
|
379
383
|
self.add_to_query(namespace_query)
|
|
380
384
|
|
|
@@ -384,8 +388,13 @@ class IPPrefixReconcileQuery(Query):
|
|
|
384
388
|
// ------------------
|
|
385
389
|
// Get IP Prefix node by UUID
|
|
386
390
|
// ------------------
|
|
387
|
-
MATCH (ip_node:%(ip_kind)s {uuid: $node_uuid})
|
|
391
|
+
OPTIONAL MATCH (ip_node:%(ip_kind)s {uuid: $node_uuid})-[r:IS_PART_OF]->(:Root)
|
|
392
|
+
WHERE %(branch_filter)s
|
|
393
|
+
ORDER BY r.branch_level DESC, r.from DESC, r.status ASC
|
|
394
|
+
LIMIT 1
|
|
395
|
+
WITH ip_namespace, ip_node
|
|
388
396
|
""" % {
|
|
397
|
+
"branch_filter": branch_filter,
|
|
389
398
|
"ip_kind": InfrahubKind.IPADDRESS
|
|
390
399
|
if isinstance(self.ip_value, IPAddressType)
|
|
391
400
|
else InfrahubKind.IPPREFIX,
|
|
@@ -395,17 +404,35 @@ class IPPrefixReconcileQuery(Query):
|
|
|
395
404
|
else:
|
|
396
405
|
get_node_by_prefix_query = """
|
|
397
406
|
// ------------------
|
|
398
|
-
// Get IP
|
|
407
|
+
// Get IP node with the correct value on this branch
|
|
399
408
|
// ------------------
|
|
400
|
-
OPTIONAL MATCH
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
-[:IS_RELATED]-(ip_node)
|
|
404
|
-
WHERE nsr.name IN ["ip_namespace__ip_prefix", "ip_namespace__ip_address"]
|
|
405
|
-
AND aipn.binary_address = $prefix_binary_full
|
|
409
|
+
OPTIONAL MATCH (:Root)<-[r1:IS_PART_OF]-(ip_node:%(ip_kind)s)
|
|
410
|
+
-[r2:HAS_ATTRIBUTE]->(a:Attribute)-[r3:HAS_VALUE]->(aipn:%(ip_attribute_kind)s)
|
|
411
|
+
WHERE aipn.binary_address = $prefix_binary_full
|
|
406
412
|
AND aipn.prefixlen = $prefixlen
|
|
407
413
|
AND aipn.version = $ip_version
|
|
408
|
-
AND all(r IN
|
|
414
|
+
AND all(r IN [r1, r2, r3] WHERE (%(branch_filter)s))
|
|
415
|
+
ORDER BY r3.branch_level DESC, r3.from DESC, r3.status ASC,
|
|
416
|
+
r2.branch_level DESC, r2.from DESC, r2.status ASC,
|
|
417
|
+
r1.branch_level DESC, r1.from DESC, r1.status ASC
|
|
418
|
+
LIMIT 1
|
|
419
|
+
WITH ip_namespace, CASE
|
|
420
|
+
WHEN ip_node IS NOT NULL AND r1.status = "active" AND r2.status = "active" AND r3.status = "active" THEN ip_node
|
|
421
|
+
ELSE NULL
|
|
422
|
+
END AS ip_node
|
|
423
|
+
// ------------------
|
|
424
|
+
// Filter to only those that are in the correct namespace
|
|
425
|
+
// ------------------
|
|
426
|
+
OPTIONAL MATCH (ip_namespace)-[r1:IS_RELATED]-(nsr:Relationship)-[r2:IS_RELATED]-(ip_node)
|
|
427
|
+
WHERE nsr.name IN ["ip_namespace__ip_prefix", "ip_namespace__ip_address"]
|
|
428
|
+
AND all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
429
|
+
ORDER BY r1.branch_level DESC, r1.from DESC, r1.status ASC,
|
|
430
|
+
r2.branch_level DESC, r2.from DESC, r2.status ASC
|
|
431
|
+
LIMIT 1
|
|
432
|
+
WITH ip_namespace, CASE
|
|
433
|
+
WHEN ip_node IS NOT NULL AND r1.status = "active" AND r2.status = "active" THEN ip_node
|
|
434
|
+
ELSE NULL
|
|
435
|
+
END as ip_node
|
|
409
436
|
""" % {
|
|
410
437
|
"branch_filter": branch_filter,
|
|
411
438
|
"ip_kind": InfrahubKind.IPADDRESS
|
|
@@ -425,7 +452,7 @@ class IPPrefixReconcileQuery(Query):
|
|
|
425
452
|
OPTIONAL MATCH parent_prefix_path = (ip_node)-[r1:IS_RELATED]->(:Relationship {name: "parent__child"})-[r2:IS_RELATED]->(current_parent:%(ip_prefix_kind)s)
|
|
426
453
|
WHERE all(r IN relationships(parent_prefix_path) WHERE (%(branch_filter)s))
|
|
427
454
|
RETURN current_parent, (r1.status = "active" AND r2.status = "active") AS parent_is_active
|
|
428
|
-
ORDER BY r1.branch_level DESC, r2.branch_level DESC,
|
|
455
|
+
ORDER BY r1.branch_level DESC, r1.from DESC, r1.status ASC, r2.branch_level DESC, r2.from DESC, r2.status ASC
|
|
429
456
|
LIMIT 1
|
|
430
457
|
}
|
|
431
458
|
WITH ip_namespace, ip_node, CASE WHEN parent_is_active THEN current_parent ELSE NULL END as current_parent
|
|
@@ -474,28 +501,66 @@ class IPPrefixReconcileQuery(Query):
|
|
|
474
501
|
// Identify the correct parent, if any, for the prefix node
|
|
475
502
|
// ------------------
|
|
476
503
|
CALL (ip_namespace) {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
WHERE all(r IN relationships(parent_path) WHERE (%(branch_filter)s))
|
|
483
|
-
AND av.version = $ip_version
|
|
504
|
+
// ------------------
|
|
505
|
+
// start with just the AttributeValue vertices b/c we have an index on them
|
|
506
|
+
// ------------------
|
|
507
|
+
OPTIONAL MATCH (av:%(ip_prefix_attribute_kind)s)
|
|
508
|
+
WHERE av.version = $ip_version
|
|
484
509
|
AND av.binary_address IN $possible_prefix_list
|
|
485
510
|
AND any(prefix_and_length IN $possible_prefix_and_length_list WHERE av.binary_address = prefix_and_length[0] AND av.prefixlen <= prefix_and_length[1])
|
|
511
|
+
// ------------------
|
|
512
|
+
// now get all the possible IPPrefix nodes for these AttributeValues
|
|
513
|
+
// ------------------
|
|
514
|
+
OPTIONAL MATCH parent_path = (ip_namespace)-[:IS_RELATED]-(:Relationship {name: "ip_namespace__ip_prefix"})
|
|
515
|
+
-[:IS_RELATED]-(maybe_new_parent:%(ip_prefix_kind)s)
|
|
516
|
+
-[:HAS_ATTRIBUTE]->(:Attribute {name: "prefix"})
|
|
517
|
+
-[:HAS_VALUE]->(av:AttributeValue)
|
|
518
|
+
WHERE all(r IN relationships(parent_path) WHERE (%(branch_filter)s))
|
|
519
|
+
RETURN DISTINCT maybe_new_parent
|
|
520
|
+
}
|
|
521
|
+
CALL (ip_namespace, maybe_new_parent) {
|
|
522
|
+
// ------------------
|
|
523
|
+
// filter to only active maybe_new_parent Nodes in the correct namespace
|
|
524
|
+
// ------------------
|
|
525
|
+
OPTIONAL MATCH (ip_namespace)-[r1:IS_RELATED]-(:Relationship {name: "ip_namespace__ip_prefix"})-[r2:IS_RELATED]-(maybe_new_parent)
|
|
526
|
+
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
527
|
+
WITH maybe_new_parent, r1, r2, r1.status = "active" AND r2.status = "active" AS is_active
|
|
528
|
+
ORDER BY elementId(maybe_new_parent), r1.branch_level DESC, r1.from DESC, r1.status ASC, r2.branch_level DESC, r2.from DESC, r2.status ASC
|
|
529
|
+
WITH maybe_new_parent, head(collect(is_active)) AS is_active
|
|
530
|
+
RETURN is_active = TRUE AS parent_in_namespace
|
|
531
|
+
}
|
|
532
|
+
CALL (maybe_new_parent) {
|
|
533
|
+
// ------------------
|
|
534
|
+
// filter to only active maybe_new_parent Nodes currently linked to one of the allowed AttributeValues
|
|
535
|
+
// ------------------
|
|
536
|
+
OPTIONAL MATCH (maybe_new_parent)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "prefix"})-[r2:HAS_VALUE]->(av:AttributeValue)
|
|
537
|
+
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
538
|
+
WITH maybe_new_parent, av, r1, r2, r1.status = "active" AND r2.status = "active" AS is_active
|
|
539
|
+
ORDER BY elementId(maybe_new_parent), r1.branch_level DESC, r1.from DESC, r1.status ASC, r2.branch_level DESC, r2.from DESC, r2.status ASC
|
|
540
|
+
// ------------------
|
|
541
|
+
// get the latest active attribute value for the maybe_new_parent
|
|
542
|
+
// ------------------
|
|
543
|
+
WITH maybe_new_parent, head(collect([av, is_active])) AS av_is_active
|
|
486
544
|
WITH
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
545
|
+
av_is_active[0] AS av,
|
|
546
|
+
av_is_active[1] AS is_active
|
|
547
|
+
// ------------------
|
|
548
|
+
// return NULL if the value is not allowed or if it is not active
|
|
549
|
+
// ------------------
|
|
550
|
+
WITH av, is_active, (
|
|
551
|
+
av.version = $ip_version
|
|
552
|
+
AND av.binary_address IN $possible_prefix_list
|
|
553
|
+
AND any(prefix_and_length IN $possible_prefix_and_length_list WHERE av.binary_address = prefix_and_length[0] AND av.prefixlen <= prefix_and_length[1])
|
|
554
|
+
) AS is_allowed_value
|
|
555
|
+
RETURN CASE WHEN is_active = TRUE AND is_allowed_value = TRUE THEN av ELSE NULL END AS allowed_av
|
|
496
556
|
}
|
|
497
|
-
|
|
498
|
-
|
|
557
|
+
// ------------------
|
|
558
|
+
// set inactive maybe_new_parents to NULL
|
|
559
|
+
// ------------------
|
|
560
|
+
WITH ip_namespace, ip_node, current_parent, current_children, allowed_av.prefixlen AS mnp_prefixlen,
|
|
561
|
+
CASE WHEN parent_in_namespace = TRUE AND allowed_av IS NOT NULL
|
|
562
|
+
THEN maybe_new_parent ELSE NULL
|
|
563
|
+
END AS maybe_new_parent
|
|
499
564
|
WITH ip_namespace, ip_node, current_parent, current_children, maybe_new_parent, mnp_prefixlen
|
|
500
565
|
ORDER BY ip_node.uuid, mnp_prefixlen DESC
|
|
501
566
|
WITH ip_namespace, ip_node, current_parent, current_children, head(collect(maybe_new_parent)) as new_parent
|
|
@@ -511,19 +576,18 @@ class IPPrefixReconcileQuery(Query):
|
|
|
511
576
|
// Identify the correct children, if any, for the prefix node
|
|
512
577
|
// ------------------
|
|
513
578
|
CALL (ip_namespace, ip_node) {
|
|
579
|
+
// ------------------
|
|
514
580
|
// Get ALL possible children for the prefix node
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
-(ns_rel:Relationship)-[
|
|
518
|
-
-(maybe_new_child:%(ip_prefix_kind)s|%(ip_address_kind)s)-[
|
|
519
|
-
->(a:Attribute)-[
|
|
520
|
-
->(av:%(ip_prefix_attribute_kind)s|%(ip_address_attribute_kind)s)
|
|
581
|
+
// ------------------
|
|
582
|
+
OPTIONAL MATCH (
|
|
583
|
+
(ip_namespace)-[:IS_RELATED]-(ns_rel:Relationship)-[:IS_RELATED]
|
|
584
|
+
-(maybe_new_child:%(ip_prefix_kind)s|%(ip_address_kind)s)-[:HAS_ATTRIBUTE]
|
|
585
|
+
->(a:Attribute)-[:HAS_VALUE]->(av:%(ip_prefix_attribute_kind)s|%(ip_address_attribute_kind)s)
|
|
521
586
|
)
|
|
522
587
|
USING INDEX av:%(ip_prefix_attribute_kind)s(binary_address)
|
|
523
588
|
USING INDEX av:%(ip_address_attribute_kind)s(binary_address)
|
|
524
589
|
WHERE $is_prefix // only prefix nodes can have children
|
|
525
590
|
AND ns_rel.name IN ["ip_namespace__ip_prefix", "ip_namespace__ip_address"]
|
|
526
|
-
AND any(child_kind IN [$ip_prefix_kind, $ip_address_kind] WHERE child_kind IN labels(maybe_new_child))
|
|
527
591
|
AND a.name in ["prefix", "address"]
|
|
528
592
|
AND (ip_node IS NULL OR maybe_new_child.uuid <> ip_node.uuid)
|
|
529
593
|
AND (
|
|
@@ -532,22 +596,58 @@ class IPPrefixReconcileQuery(Query):
|
|
|
532
596
|
)
|
|
533
597
|
AND av.version = $ip_version
|
|
534
598
|
AND av.binary_address STARTS WITH $prefix_binary_host
|
|
535
|
-
|
|
599
|
+
RETURN DISTINCT maybe_new_child
|
|
600
|
+
}
|
|
601
|
+
CALL (ip_namespace, maybe_new_child) {
|
|
602
|
+
// ------------------
|
|
603
|
+
// filter to only active maybe_new_child Nodes in the correct namespace
|
|
604
|
+
// ------------------
|
|
605
|
+
OPTIONAL MATCH (ip_namespace)-[r1:IS_RELATED]-(ns_rel:Relationship)-[r2:IS_RELATED]-(maybe_new_child)
|
|
606
|
+
WHERE ns_rel.name IN ["ip_namespace__ip_prefix", "ip_namespace__ip_address"]
|
|
607
|
+
AND all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
608
|
+
WITH maybe_new_child, r1, r2, r1.status = "active" AND r2.status = "active" AS is_active
|
|
609
|
+
ORDER BY elementId(maybe_new_child), r1.branch_level DESC, r1.from DESC, r1.status ASC, r2.branch_level DESC, r2.from DESC, r2.status ASC
|
|
610
|
+
WITH maybe_new_child, head(collect(is_active)) AS is_active
|
|
611
|
+
RETURN is_active = TRUE AS child_in_namespace
|
|
612
|
+
}
|
|
613
|
+
CALL (maybe_new_child) {
|
|
614
|
+
// ------------------
|
|
615
|
+
// filter to only active maybe_new_child Nodes currently linked to a possible child AttributeValue
|
|
616
|
+
// ------------------
|
|
617
|
+
OPTIONAL MATCH (maybe_new_child:%(ip_prefix_kind)s|%(ip_address_kind)s)-[r1:HAS_ATTRIBUTE]->(a:Attribute)-[r2:HAS_VALUE]->(av:AttributeValue)
|
|
618
|
+
WHERE a.name in ["prefix", "address"]
|
|
619
|
+
AND all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
620
|
+
WITH maybe_new_child, av, r1, r2, r1.status = "active" AND r2.status = "active" AS is_active
|
|
621
|
+
ORDER BY elementId(maybe_new_child), r1.branch_level DESC, r1.from DESC, r1.status ASC, r2.branch_level DESC, r2.from DESC, r2.status ASC
|
|
622
|
+
// ------------------
|
|
623
|
+
// get the latest active attribute value for the maybe_new_child
|
|
624
|
+
// ------------------
|
|
625
|
+
WITH maybe_new_child, head(collect([av, is_active])) AS av_is_active
|
|
536
626
|
WITH
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
627
|
+
av_is_active[0] AS av,
|
|
628
|
+
av_is_active[1] AS is_active
|
|
629
|
+
// ------------------
|
|
630
|
+
// return NULL if the value is not allowed or if it is not active
|
|
631
|
+
// ------------------
|
|
632
|
+
WITH av, is_active, (
|
|
633
|
+
(
|
|
634
|
+
($ip_prefix_kind IN labels(maybe_new_child) AND av.prefixlen > $prefixlen)
|
|
635
|
+
OR ($ip_address_kind IN labels(maybe_new_child) AND av.prefixlen >= $prefixlen)
|
|
636
|
+
)
|
|
637
|
+
AND av.version = $ip_version
|
|
638
|
+
AND av.binary_address STARTS WITH $prefix_binary_host
|
|
639
|
+
) AS is_allowed_value
|
|
640
|
+
RETURN CASE WHEN is_active = TRUE AND is_allowed_value = TRUE THEN av ELSE NULL END AS latest_mnc_attribute
|
|
548
641
|
}
|
|
549
|
-
|
|
550
|
-
|
|
642
|
+
// ------------------
|
|
643
|
+
// set inactive/illegal value/wrong namespace maybe_new_children to NULL
|
|
644
|
+
// ------------------
|
|
645
|
+
WITH ip_namespace, ip_node, current_parent, current_children, new_parent,
|
|
646
|
+
CASE
|
|
647
|
+
WHEN child_in_namespace = TRUE AND latest_mnc_attribute IS NOT NULL THEN maybe_new_child
|
|
648
|
+
ELSE NULL
|
|
649
|
+
END AS maybe_new_child,
|
|
650
|
+
CASE WHEN child_in_namespace = TRUE THEN latest_mnc_attribute ELSE NULL END AS latest_mnc_attribute
|
|
551
651
|
WITH ip_namespace, ip_node, current_parent, current_children, new_parent, collect([maybe_new_child, latest_mnc_attribute]) AS maybe_children_ips
|
|
552
652
|
WITH ip_namespace, ip_node, current_parent, current_children, new_parent, maybe_children_ips, range(0, size(maybe_children_ips) - 1) AS child_indices
|
|
553
653
|
UNWIND child_indices as ind
|
|
@@ -581,9 +681,9 @@ class IPPrefixReconcileQuery(Query):
|
|
|
581
681
|
new_parent,
|
|
582
682
|
collect(new_child) as new_children
|
|
583
683
|
""" % {
|
|
584
|
-
"branch_filter": branch_filter,
|
|
585
684
|
"ip_prefix_kind": InfrahubKind.IPPREFIX,
|
|
586
685
|
"ip_address_kind": InfrahubKind.IPADDRESS,
|
|
686
|
+
"branch_filter": branch_filter,
|
|
587
687
|
"ip_prefix_attribute_kind": PREFIX_ATTRIBUTE_LABEL,
|
|
588
688
|
"ip_address_attribute_kind": ADDRESS_ATTRIBUTE_LABEL,
|
|
589
689
|
}
|
infrahub/generators/tasks.py
CHANGED
|
@@ -168,6 +168,15 @@ async def request_generator_definition_run(
|
|
|
168
168
|
|
|
169
169
|
client = get_client()
|
|
170
170
|
|
|
171
|
+
# Needs to be fetched before fetching group members otherwise `object` relationship would override
|
|
172
|
+
# existing node in client store without the `name` attribute due to #521
|
|
173
|
+
existing_instances = await client.filters(
|
|
174
|
+
kind=InfrahubKind.GENERATORINSTANCE,
|
|
175
|
+
definition__ids=[model.generator_definition.definition_id],
|
|
176
|
+
include=["object"],
|
|
177
|
+
branch=model.branch,
|
|
178
|
+
)
|
|
179
|
+
|
|
171
180
|
group = await client.get(
|
|
172
181
|
kind=InfrahubKind.GENERICGROUP,
|
|
173
182
|
prefetch_relationships=True,
|
|
@@ -177,12 +186,6 @@ async def request_generator_definition_run(
|
|
|
177
186
|
)
|
|
178
187
|
await group.members.fetch()
|
|
179
188
|
|
|
180
|
-
existing_instances = await client.filters(
|
|
181
|
-
kind=InfrahubKind.GENERATORINSTANCE,
|
|
182
|
-
definition__ids=[model.generator_definition.definition_id],
|
|
183
|
-
include=["object"],
|
|
184
|
-
branch=model.branch,
|
|
185
|
-
)
|
|
186
189
|
instance_by_member = {}
|
|
187
190
|
for instance in existing_instances:
|
|
188
191
|
instance_by_member[instance.object.peer.id] = instance.id
|
infrahub/git/tasks.py
CHANGED
|
@@ -310,6 +310,15 @@ async def generate_request_artifact_definition(
|
|
|
310
310
|
|
|
311
311
|
client = get_client()
|
|
312
312
|
|
|
313
|
+
# Needs to be fetched before fetching group members otherwise `object` relationship would override
|
|
314
|
+
# existing node in client store without the `name` attribute due to #521
|
|
315
|
+
existing_artifacts = await client.filters(
|
|
316
|
+
kind=CoreArtifact,
|
|
317
|
+
definition__ids=[model.artifact_definition_id],
|
|
318
|
+
include=["object"],
|
|
319
|
+
branch=model.branch,
|
|
320
|
+
)
|
|
321
|
+
|
|
313
322
|
artifact_definition = await client.get(
|
|
314
323
|
kind=CoreArtifactDefinition, id=model.artifact_definition_id, branch=model.branch
|
|
315
324
|
)
|
|
@@ -319,12 +328,6 @@ async def generate_request_artifact_definition(
|
|
|
319
328
|
await group.members.fetch()
|
|
320
329
|
current_members = [member.id for member in group.members.peers]
|
|
321
330
|
|
|
322
|
-
existing_artifacts = await client.filters(
|
|
323
|
-
kind=CoreArtifact,
|
|
324
|
-
definition__ids=[model.artifact_definition_id],
|
|
325
|
-
include=["object"],
|
|
326
|
-
branch=model.branch,
|
|
327
|
-
)
|
|
328
331
|
artifacts_by_member = {}
|
|
329
332
|
for artifact in existing_artifacts:
|
|
330
333
|
if artifact.object.id in current_members:
|
|
@@ -646,16 +646,19 @@ async def validate_artifacts_generation(model: RequestArtifactDefinitionCheck, c
|
|
|
646
646
|
context=context,
|
|
647
647
|
)
|
|
648
648
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
await group.members.fetch()
|
|
652
|
-
|
|
649
|
+
# Needs to be fetched before fetching group members otherwise `object` relationship would override
|
|
650
|
+
# existing node in client store without the `name` attribute due to #521
|
|
653
651
|
existing_artifacts = await client.filters(
|
|
654
652
|
kind=InfrahubKind.ARTIFACT,
|
|
655
653
|
definition__ids=[model.artifact_definition.definition_id],
|
|
656
654
|
include=["object"],
|
|
657
655
|
branch=model.source_branch,
|
|
658
656
|
)
|
|
657
|
+
|
|
658
|
+
await artifact_definition.targets.fetch()
|
|
659
|
+
group = artifact_definition.targets.peer
|
|
660
|
+
await group.members.fetch()
|
|
661
|
+
|
|
659
662
|
artifacts_by_member = {}
|
|
660
663
|
for artifact in existing_artifacts:
|
|
661
664
|
artifacts_by_member[artifact.object.peer.id] = artifact.id
|
|
@@ -907,6 +910,15 @@ async def request_generator_definition_check(model: RequestGeneratorDefinitionCh
|
|
|
907
910
|
context=context,
|
|
908
911
|
)
|
|
909
912
|
|
|
913
|
+
# Needs to be fetched before fetching group members otherwise `object` relationship would override
|
|
914
|
+
# existing node in client store without the `name` attribute due to #521
|
|
915
|
+
existing_instances = await client.filters(
|
|
916
|
+
kind=InfrahubKind.GENERATORINSTANCE,
|
|
917
|
+
definition__ids=[model.generator_definition.definition_id],
|
|
918
|
+
include=["object"],
|
|
919
|
+
branch=model.source_branch,
|
|
920
|
+
)
|
|
921
|
+
|
|
910
922
|
group = await client.get(
|
|
911
923
|
kind=InfrahubKind.GENERICGROUP,
|
|
912
924
|
prefetch_relationships=True,
|
|
@@ -916,12 +928,6 @@ async def request_generator_definition_check(model: RequestGeneratorDefinitionCh
|
|
|
916
928
|
)
|
|
917
929
|
await group.members.fetch()
|
|
918
930
|
|
|
919
|
-
existing_instances = await client.filters(
|
|
920
|
-
kind=InfrahubKind.GENERATORINSTANCE,
|
|
921
|
-
definition__ids=[model.generator_definition.definition_id],
|
|
922
|
-
include=["object"],
|
|
923
|
-
branch=model.source_branch,
|
|
924
|
-
)
|
|
925
931
|
instance_by_member = {}
|
|
926
932
|
for instance in existing_instances:
|
|
927
933
|
instance_by_member[instance.object.peer.id] = instance.id
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: infrahub-server
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.6
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
infrahub/__init__.py,sha256=OF6hovR3975Zu6-9DOL_Nh_FTgGn8kS_yOfQ-xp-chg,87
|
|
2
2
|
infrahub/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
infrahub/actions/constants.py,sha256=
|
|
3
|
+
infrahub/actions/constants.py,sha256=xrVNdwBwCzG20eXfowV3bia3LW8Kwx-DazS6vALPbEg,3790
|
|
4
4
|
infrahub/actions/gather.py,sha256=s6RaegkD9zx7WL8ePS6eGam8TlUA3TH38tarLmQeT98,4746
|
|
5
5
|
infrahub/actions/models.py,sha256=7EVJuGLqEy71sop1XEDLpuAZfLc9ei3hxXPy2FeyY4U,8558
|
|
6
6
|
infrahub/actions/parsers.py,sha256=L0ZE2gvhSoBZHuHok0wO4UeWo8fyhbnpuMTHHZX_W7c,3997
|
|
@@ -21,7 +21,7 @@ infrahub/api/internal.py,sha256=ZlE5BkdGcrmLq1RZOCvv8OBBL7iT7wHKGG9Kqc-TTKg,5339
|
|
|
21
21
|
infrahub/api/menu.py,sha256=xp5bj5JXQZA6ZEPWoTSGGSfTXZ1sVmehMxr3VSG7FlQ,1216
|
|
22
22
|
infrahub/api/oauth2.py,sha256=wFsWrwfyoNBC1JYzbt1nzU-OjjxWPARIBbE_14jzFmI,5493
|
|
23
23
|
infrahub/api/oidc.py,sha256=3fU-fNOoMkqEzoLuTmlhCVaZvL6M3sAub8RP1_LvCO8,8299
|
|
24
|
-
infrahub/api/query.py,sha256=
|
|
24
|
+
infrahub/api/query.py,sha256=xc5aAY0TLHnswdjiIpvThG974EKGVIXvZCbtdiiZkPw,7312
|
|
25
25
|
infrahub/api/schema.py,sha256=dUSB51YXaWELZuXYI7UNemd60MJPPBv4m6-MexXOE0k,17450
|
|
26
26
|
infrahub/api/static/redoc.standalone.js,sha256=77kGx7mVN9EcdER2ZM4gQ-E-ra_N6AZq9QseAeD6kt0,1042008
|
|
27
27
|
infrahub/api/static/swagger-ui-bundle.js,sha256=wuSp7wgUSDn_R8FCAgY-z-TlnnCk5xVKJr1Q2IDIi6E,1452753
|
|
@@ -61,7 +61,7 @@ infrahub/constants/database.py,sha256=WmV1iuOk4xulxZHOVvO3sS_VF1eTf7fKh0TPe_RnfV
|
|
|
61
61
|
infrahub/constants/environment.py,sha256=ry-6qsBzSumOjjiq1D3XNoquf1LWqFKiQSJj8t6nET4,32
|
|
62
62
|
infrahub/context.py,sha256=8SZRKSECkkcsNNzDaKEUJ7Nyr0EzUfToAy969LXjQVk,1554
|
|
63
63
|
infrahub/core/__init__.py,sha256=z6EJBZyCYCBqinoBtX9li6BTBbbGV8WCkE_4CrEsmDA,104
|
|
64
|
-
infrahub/core/account.py,sha256=
|
|
64
|
+
infrahub/core/account.py,sha256=6f1cIDWvL-HsbzL0UwWoCbDTzx55wzd_SkpQXiKDjcE,27477
|
|
65
65
|
infrahub/core/attribute.py,sha256=f1-XLuRzbpG7T8y6pqQQqxQkbGDWhS5AZA2_r_mzY-A,44537
|
|
66
66
|
infrahub/core/branch/__init__.py,sha256=h0oIj0gHp1xI-N1cYW8_N6VZ81CBOmLuiUt5cS5nKuk,49
|
|
67
67
|
infrahub/core/branch/enums.py,sha256=vGnaTCzikvMcLikKN25TJ8uCmhnD448dp1ve1_tLjwQ,186
|
|
@@ -241,7 +241,7 @@ infrahub/core/query/attribute.py,sha256=xojZIHX-XfXlN_jgM1TQ1Bp4dXr4oLEWlr2A7igT
|
|
|
241
241
|
infrahub/core/query/branch.py,sha256=7gj83jDWPWjFUZud7lMQ0xwl9ag3FL-ZOlmY5Kuq7UU,4307
|
|
242
242
|
infrahub/core/query/delete.py,sha256=7tPP1qtNV6QGYtmgE1RKsuQ9oxENnMTVkttLvJ2PiKg,1927
|
|
243
243
|
infrahub/core/query/diff.py,sha256=jJCkZRo5jGaf-yPAnQ_5ju6sCnknDK0E7vGpqEnaU_k,36881
|
|
244
|
-
infrahub/core/query/ipam.py,sha256=
|
|
244
|
+
infrahub/core/query/ipam.py,sha256=dOs_LZr-DONrCPw6t5Ug9mBPn8a-S2NKja3Vr-zIeaM,34523
|
|
245
245
|
infrahub/core/query/node.py,sha256=OfWS9PfltP89aU4n0KhEjrvAkhAGj9Vl4hcfKcE9LD8,70969
|
|
246
246
|
infrahub/core/query/relationship.py,sha256=KmS9zrcr-RViXxiITXOjq1t0s-AfsICHk3wyyirZBfA,47817
|
|
247
247
|
infrahub/core/query/resource_manager.py,sha256=uSvs1WZmdbyt_PjaUi9lXnYdPt-lhJV1RjYoUHYjQdk,16620
|
|
@@ -434,7 +434,7 @@ infrahub/events/validator_action.py,sha256=nQJH-RWcgr3-tzmIldvPmu5O7dUAmv1qQnuxx
|
|
|
434
434
|
infrahub/exceptions.py,sha256=cbM-f_2U-5ZFVZ_MaaXgs64k4M7uJ7fqDU2iCRoWlYY,11861
|
|
435
435
|
infrahub/generators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
436
436
|
infrahub/generators/models.py,sha256=9qhSfsoG-uYux35HClAxSq7TRfkosqN3i_eQkeTokLs,1916
|
|
437
|
-
infrahub/generators/tasks.py,sha256=
|
|
437
|
+
infrahub/generators/tasks.py,sha256=Ci6lIbnUS6faGzbUjw1ggROpv17guZ-Z9HH9f6cAZv4,9563
|
|
438
438
|
infrahub/git/__init__.py,sha256=KeQ9U8UI5jDj6KB6j00Oal7MZmtOD9vKqVgiezG_EQA,281
|
|
439
439
|
infrahub/git/base.py,sha256=RNXow4RzTBJyjTmT1vZO9_DZSx4Dyv12M-bK_xTBTbg,38657
|
|
440
440
|
infrahub/git/constants.py,sha256=XpzcAkXbsgXZgrXey74id1sXV8Q6EHb_4FNw7BndxyY,106
|
|
@@ -442,7 +442,7 @@ infrahub/git/directory.py,sha256=fozxLXXJPweHG95yQwQkR5yy3sfTdmHiczCAJnsUX54,861
|
|
|
442
442
|
infrahub/git/integrator.py,sha256=C9h1qo8EVE8FjwzGWHhTD50I8TuCTH9asgC8-z5eK-g,62818
|
|
443
443
|
infrahub/git/models.py,sha256=ozk9alxQ8Ops1lw1g8iR3O7INuw1VPsEUr5Wceh9HQY,12152
|
|
444
444
|
infrahub/git/repository.py,sha256=wPsJAA9aHTHdfw0gqCfkNHvcivs7JabsDf-uazptZt0,10928
|
|
445
|
-
infrahub/git/tasks.py,sha256=
|
|
445
|
+
infrahub/git/tasks.py,sha256=aBFN7yV72UshcxFljrmHAKGSDoe0e1eVjrnyPDXQEM8,37515
|
|
446
446
|
infrahub/git/utils.py,sha256=xhWxlu_FbMqbrwanpPkex4hKRS_d2AFzlxI_6kVQllw,1741
|
|
447
447
|
infrahub/git/worktree.py,sha256=8IYJWOBytKUWwhMmMVehR4ceeO9e13nV-mvn3iVEgZY,1727
|
|
448
448
|
infrahub/git_credential/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -622,7 +622,7 @@ infrahub/proposed_change/branch_diff.py,sha256=IdMxf5zPmhybQKPPz7AlruNmLCKf5VISP
|
|
|
622
622
|
infrahub/proposed_change/checker.py,sha256=ZhNEVJKsQbHH2UE1O35MfOVa8cK1QGEqGyn6MsOuqSQ,1558
|
|
623
623
|
infrahub/proposed_change/constants.py,sha256=auifG94Oo2cJ4RwZx4P-XDPDpKYPtEVxh013KPfiEdU,2080
|
|
624
624
|
infrahub/proposed_change/models.py,sha256=ivWJmEAihprKmwgaBGDJ4Koq4ETciE5GfDp86KHDnns,5892
|
|
625
|
-
infrahub/proposed_change/tasks.py,sha256
|
|
625
|
+
infrahub/proposed_change/tasks.py,sha256=M1vdCE1J_IBxGwSnQLWwobxhOSDaaxuvEScgZuYbus8,63991
|
|
626
626
|
infrahub/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
627
627
|
infrahub/pytest_plugin.py,sha256=u3t0WgLMo9XmuQYeb28mccQ3xbnyv2Fv173YWl1zBiM,6678
|
|
628
628
|
infrahub/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -827,8 +827,8 @@ infrahub_testcontainers/models.py,sha256=ASYyvl7d_WQz_i7y8-3iab9hwwmCl3OCJavqVbe
|
|
|
827
827
|
infrahub_testcontainers/performance_test.py,sha256=hvwiy6tc_lWniYqGkqfOXVGAmA_IV15VOZqbiD9ezno,6149
|
|
828
828
|
infrahub_testcontainers/plugin.py,sha256=I3RuZQ0dARyKHuqCf0y1Yj731P2Mwf3BJUehRJKeWrs,5645
|
|
829
829
|
infrahub_testcontainers/prometheus.yml,sha256=610xQEyj3xuVJMzPkC4m1fRnCrjGpiRBrXA2ytCLa54,599
|
|
830
|
-
infrahub_server-1.4.
|
|
831
|
-
infrahub_server-1.4.
|
|
832
|
-
infrahub_server-1.4.
|
|
833
|
-
infrahub_server-1.4.
|
|
834
|
-
infrahub_server-1.4.
|
|
830
|
+
infrahub_server-1.4.6.dist-info/LICENSE.txt,sha256=7GQO7kxVoQYnZtFrjZBKLRXbrGwwwimHPPOJtqXsozQ,11340
|
|
831
|
+
infrahub_server-1.4.6.dist-info/METADATA,sha256=O5wCV3t2TuX9o4kj49ujsXIigL20YFpkMBU6-PWY7kE,8277
|
|
832
|
+
infrahub_server-1.4.6.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
833
|
+
infrahub_server-1.4.6.dist-info/entry_points.txt,sha256=UXIeFWDsrV-4IllNvUEd6KieYGzQfn9paga2YyABOQI,393
|
|
834
|
+
infrahub_server-1.4.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|