infrahub-server 1.6.1__py3-none-any.whl → 1.6.3__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/core/account.py +8 -5
- infrahub/core/branch/tasks.py +6 -1
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/migrations/graph/__init__.py +2 -0
- infrahub/core/migrations/graph/m041_deleted_dup_edges.py +30 -12
- infrahub/core/migrations/graph/m048_undelete_rel_props.py +161 -0
- infrahub/core/migrations/schema/attribute_kind_update.py +5 -4
- infrahub/core/query/__init__.py +6 -3
- infrahub/core/schema/attribute_parameters.py +28 -1
- infrahub/core/schema/attribute_schema.py +9 -15
- infrahub/core/schema/schema_branch.py +67 -1
- infrahub/core/validators/attribute/kind.py +5 -2
- infrahub/graphql/app.py +2 -2
- infrahub/graphql/queries/diff/tree.py +5 -5
- {infrahub_server-1.6.1.dist-info → infrahub_server-1.6.3.dist-info}/METADATA +1 -1
- {infrahub_server-1.6.1.dist-info → infrahub_server-1.6.3.dist-info}/RECORD +19 -18
- {infrahub_server-1.6.1.dist-info → infrahub_server-1.6.3.dist-info}/WHEEL +0 -0
- {infrahub_server-1.6.1.dist-info → infrahub_server-1.6.3.dist-info}/entry_points.txt +0 -0
- {infrahub_server-1.6.1.dist-info → infrahub_server-1.6.3.dist-info}/licenses/LICENSE.txt +0 -0
infrahub/core/account.py
CHANGED
|
@@ -54,11 +54,15 @@ class AccountGlobalPermissionQuery(Query):
|
|
|
54
54
|
name: str = "account_global_permissions"
|
|
55
55
|
type: QueryType = QueryType.READ
|
|
56
56
|
|
|
57
|
-
def __init__(
|
|
57
|
+
def __init__(
|
|
58
|
+
self,
|
|
59
|
+
account_id: str,
|
|
60
|
+
branch: Branch | None = None,
|
|
61
|
+
branch_agnostic: bool = False,
|
|
62
|
+
) -> None:
|
|
63
|
+
super().__init__(branch=branch, branch_agnostic=branch_agnostic)
|
|
58
64
|
self.account_id = account_id
|
|
59
|
-
super().__init__(**kwargs)
|
|
60
65
|
|
|
61
|
-
async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
|
|
62
66
|
self.params["account_id"] = self.account_id
|
|
63
67
|
|
|
64
68
|
branch_filter, branch_params = self.branch.get_query_filter_path(
|
|
@@ -66,7 +70,6 @@ class AccountGlobalPermissionQuery(Query):
|
|
|
66
70
|
)
|
|
67
71
|
self.params.update(branch_params)
|
|
68
72
|
|
|
69
|
-
# ruff: noqa: E501
|
|
70
73
|
query = """
|
|
71
74
|
MATCH (account:%(generic_account_node)s)
|
|
72
75
|
WHERE account.uuid = $account_id
|
|
@@ -293,7 +296,7 @@ class AccountObjectPermissionQuery(Query):
|
|
|
293
296
|
|
|
294
297
|
|
|
295
298
|
async def fetch_permissions(account_id: str, db: InfrahubDatabase, branch: Branch) -> AssignedPermissions:
|
|
296
|
-
query1 =
|
|
299
|
+
query1 = AccountGlobalPermissionQuery(branch=branch, account_id=account_id, branch_agnostic=True)
|
|
297
300
|
await query1.execute(db=db)
|
|
298
301
|
global_permissions = query1.get_permissions()
|
|
299
302
|
|
infrahub/core/branch/tasks.py
CHANGED
|
@@ -157,7 +157,12 @@ async def rebase_branch(branch: str, context: InfrahubContext, send_events: bool
|
|
|
157
157
|
responses = await schema_validate_migrations(
|
|
158
158
|
message=SchemaValidateMigrationData(branch=obj, schema_branch=candidate_schema, constraints=constraints)
|
|
159
159
|
)
|
|
160
|
-
error_messages = [
|
|
160
|
+
error_messages = [
|
|
161
|
+
f"{violation.message} for constraint {response.constraint_name} {response.schema_path.field_name} {response.schema_path.property_name} and node {violation.node_id} {violation.node_kind}" # noqa: E501
|
|
162
|
+
for response in responses
|
|
163
|
+
for violation in response.violations
|
|
164
|
+
]
|
|
165
|
+
|
|
161
166
|
if error_messages:
|
|
162
167
|
raise ValidationError(",\n".join(error_messages))
|
|
163
168
|
|
infrahub/core/graph/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
GRAPH_VERSION =
|
|
1
|
+
GRAPH_VERSION = 48
|
|
@@ -49,6 +49,7 @@ from .m044_backfill_hfid_display_label_in_db import Migration044
|
|
|
49
49
|
from .m045_backfill_hfid_display_label_in_db_profile_template import Migration045
|
|
50
50
|
from .m046_fill_agnostic_hfid_display_labels import Migration046
|
|
51
51
|
from .m047_backfill_or_null_display_label import Migration047
|
|
52
|
+
from .m048_undelete_rel_props import Migration048
|
|
52
53
|
|
|
53
54
|
if TYPE_CHECKING:
|
|
54
55
|
from ..shared import MigrationTypes
|
|
@@ -102,6 +103,7 @@ MIGRATIONS: list[type[MigrationTypes]] = [
|
|
|
102
103
|
Migration045,
|
|
103
104
|
Migration046,
|
|
104
105
|
Migration047,
|
|
106
|
+
Migration048,
|
|
105
107
|
]
|
|
106
108
|
|
|
107
109
|
|
|
@@ -68,33 +68,49 @@ DELETE added_e
|
|
|
68
68
|
self.add_to_query(query)
|
|
69
69
|
|
|
70
70
|
|
|
71
|
-
class
|
|
72
|
-
name = "
|
|
71
|
+
class DeleteDuplicatedRelationshipEdges(Query):
|
|
72
|
+
name = "delete_duplicated_relationship_edges_query"
|
|
73
73
|
type = QueryType.WRITE
|
|
74
74
|
insert_return = False
|
|
75
75
|
|
|
76
|
+
def __init__(self, migrated_kind_nodes_only: bool = True, **kwargs: Any):
|
|
77
|
+
self.migrated_kind_nodes_only = migrated_kind_nodes_only
|
|
78
|
+
super().__init__(**kwargs)
|
|
79
|
+
|
|
76
80
|
async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
|
|
77
|
-
|
|
81
|
+
if not self.migrated_kind_nodes_only:
|
|
82
|
+
relationship_filter_query = """
|
|
83
|
+
MATCH (rel:Relationship)
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
else:
|
|
87
|
+
relationship_filter_query = """
|
|
78
88
|
// ------------
|
|
79
89
|
// get UUIDs for migrated kind/inheritance nodes
|
|
80
90
|
// ------------
|
|
81
91
|
MATCH (n:Node)
|
|
82
92
|
WITH n.uuid AS node_uuid, count(*) AS num_nodes_with_uuid
|
|
83
93
|
WHERE num_nodes_with_uuid > 1
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
94
|
+
// ------------
|
|
95
|
+
// find any Relationships for these nodes
|
|
96
|
+
// ------------
|
|
97
|
+
MATCH (n:Node {uuid: node_uuid})-[:IS_RELATED]-(rel:Relationship)
|
|
98
|
+
WITH DISTINCT rel
|
|
99
|
+
|
|
100
|
+
"""
|
|
101
|
+
self.add_to_query(relationship_filter_query)
|
|
102
|
+
|
|
103
|
+
query = """
|
|
104
|
+
CALL (rel) {
|
|
105
|
+
MATCH (rel)-[e]-(peer)
|
|
91
106
|
WITH
|
|
107
|
+
elementId(rel) AS rel_element_id,
|
|
92
108
|
type(e) AS e_type,
|
|
93
109
|
e.branch AS e_branch,
|
|
94
110
|
e.from AS e_from,
|
|
95
111
|
e.to AS e_to,
|
|
96
112
|
e.status AS e_status,
|
|
97
|
-
|
|
113
|
+
elementId(peer) AS peer_element_id,
|
|
98
114
|
CASE
|
|
99
115
|
WHEN startNode(e) = rel THEN "out" ELSE "in"
|
|
100
116
|
END AS direction,
|
|
@@ -142,7 +158,9 @@ class Migration041(ArbitraryMigration):
|
|
|
142
158
|
rprint("done")
|
|
143
159
|
|
|
144
160
|
rprint("Deleting duplicate edges for migrated kind/inheritance nodes", end="...")
|
|
145
|
-
delete_duplicate_edges_query = await
|
|
161
|
+
delete_duplicate_edges_query = await DeleteDuplicatedRelationshipEdges.init(
|
|
162
|
+
db=db, migrated_kind_nodes_only=True
|
|
163
|
+
)
|
|
146
164
|
await delete_duplicate_edges_query.execute(db=db)
|
|
147
165
|
rprint("done")
|
|
148
166
|
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from infrahub.core.migrations.graph.m041_deleted_dup_edges import DeleteDuplicatedRelationshipEdges
|
|
6
|
+
from infrahub.core.migrations.shared import ArbitraryMigration, MigrationResult, get_migration_console
|
|
7
|
+
from infrahub.core.query import Query, QueryType
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from infrahub.database import InfrahubDatabase
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class UndeleteRelationshipProperties(Query):
|
|
14
|
+
"""
|
|
15
|
+
Find Relationship vertices that are missing IS_VISIBLE and/or IS_PROTECTED edges linking them to Boolean vertices
|
|
16
|
+
|
|
17
|
+
Use the existing IS_RELATED edges to determine when the IS_VISIBLE/IS_PROTECTED edges should exist on each branch
|
|
18
|
+
and add the missing edges
|
|
19
|
+
|
|
20
|
+
Sets IS_VISIBLE to TRUE and IS_PROTECTED to FALSE
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
name = "undelete_relationship_properties"
|
|
24
|
+
type = QueryType.WRITE
|
|
25
|
+
insert_return = False
|
|
26
|
+
|
|
27
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
|
|
28
|
+
query = """
|
|
29
|
+
// --------------
|
|
30
|
+
// find all Relationships that are missing IS_VISIBLE/IS_PROTECTED edges
|
|
31
|
+
// --------------
|
|
32
|
+
MATCH (rel:Relationship)-[:IS_RELATED]-()
|
|
33
|
+
WHERE NOT exists((rel)-[:IS_VISIBLE]->())
|
|
34
|
+
OR NOT exists((rel)-[:IS_PROTECTED]->())
|
|
35
|
+
WITH DISTINCT rel
|
|
36
|
+
WITH rel, exists((rel)-[:IS_VISIBLE]->()) AS has_visible, exists((rel)-[:IS_PROTECTED]->()) AS has_protected
|
|
37
|
+
WHERE has_visible = FALSE OR has_protected = FALSE
|
|
38
|
+
|
|
39
|
+
// --------------
|
|
40
|
+
// one row for each branch the Relationship has changes on
|
|
41
|
+
// --------------
|
|
42
|
+
CALL (rel) {
|
|
43
|
+
MATCH (rel)-[e:IS_RELATED]-()
|
|
44
|
+
RETURN DISTINCT e.branch AS branch
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// --------------
|
|
48
|
+
// get the earliest from edge on this branch, if any
|
|
49
|
+
// --------------
|
|
50
|
+
CALL (rel, branch) {
|
|
51
|
+
OPTIONAL MATCH (rel)-[e:IS_RELATED {status: "active", branch: branch}]-()
|
|
52
|
+
// ignore schema kind/inheritance migration edges
|
|
53
|
+
WHERE NOT exists((rel)-[:IS_RELATED {status: "deleted", branch: branch, from: e.from}]-())
|
|
54
|
+
RETURN e AS earliest_from_edge
|
|
55
|
+
ORDER BY e.from ASC
|
|
56
|
+
LIMIT 1
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// --------------
|
|
60
|
+
// get the latest to time on this branch, if any
|
|
61
|
+
// --------------
|
|
62
|
+
CALL (rel, branch) {
|
|
63
|
+
OPTIONAL MATCH (rel)-[e:IS_RELATED {status: "active", branch: branch}]-()
|
|
64
|
+
// ignore schema kind/inheritance migration edges
|
|
65
|
+
WHERE NOT exists((rel)-[:IS_RELATED {status: "active", branch: branch, from: e.to}]-())
|
|
66
|
+
RETURN e.to AS latest_to_time
|
|
67
|
+
ORDER BY e.to DESC
|
|
68
|
+
LIMIT 1
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// --------------
|
|
72
|
+
// get the latest deleted edge on this branch, if any
|
|
73
|
+
// --------------
|
|
74
|
+
CALL (rel, branch) {
|
|
75
|
+
OPTIONAL MATCH (rel)-[deleted_e:IS_RELATED {status: "deleted", branch: branch}]-()
|
|
76
|
+
// ignore schema kind/inheritance migration edges
|
|
77
|
+
WHERE NOT exists((rel)-[:IS_RELATED {status: "active", branch: branch, from: deleted_e.from}]-())
|
|
78
|
+
RETURN deleted_e AS latest_deleted_edge
|
|
79
|
+
ORDER BY deleted_e.from DESC
|
|
80
|
+
LIMIT 1
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// --------------
|
|
84
|
+
// add active IS_VISIBLE edge on the branch, if necessary
|
|
85
|
+
// --------------
|
|
86
|
+
CALL (rel, earliest_from_edge, latest_to_time, has_visible) {
|
|
87
|
+
WITH *, has_visible
|
|
88
|
+
WHERE has_visible = FALSE
|
|
89
|
+
AND earliest_from_edge IS NOT NULL
|
|
90
|
+
MERGE (bool:Boolean {value: TRUE})
|
|
91
|
+
CREATE (rel)-[new_edge:IS_VISIBLE]->(bool)
|
|
92
|
+
SET new_edge = properties(earliest_from_edge)
|
|
93
|
+
SET new_edge.to = latest_to_time
|
|
94
|
+
}
|
|
95
|
+
// --------------
|
|
96
|
+
// add deleted IS_VISIBLE edge on the branch, if necessary
|
|
97
|
+
// --------------
|
|
98
|
+
CALL (rel, latest_deleted_edge, has_visible) {
|
|
99
|
+
WITH *, has_visible
|
|
100
|
+
WHERE has_visible = FALSE
|
|
101
|
+
AND latest_deleted_edge IS NOT NULL
|
|
102
|
+
MERGE (bool:Boolean {value: TRUE})
|
|
103
|
+
CREATE (rel)-[new_edge:IS_VISIBLE]->(bool)
|
|
104
|
+
SET new_edge = properties(latest_deleted_edge)
|
|
105
|
+
}
|
|
106
|
+
// --------------
|
|
107
|
+
// add active IS_PROTECTED edge on the branch, if necessary
|
|
108
|
+
// --------------
|
|
109
|
+
CALL (rel, earliest_from_edge, latest_to_time, has_protected) {
|
|
110
|
+
WITH *, has_protected
|
|
111
|
+
WHERE has_protected = FALSE
|
|
112
|
+
AND earliest_from_edge IS NOT NULL
|
|
113
|
+
MERGE (bool:Boolean {value: FALSE})
|
|
114
|
+
CREATE (rel)-[new_edge:IS_PROTECTED]->(bool)
|
|
115
|
+
SET new_edge = properties(earliest_from_edge)
|
|
116
|
+
SET new_edge.to = latest_to_time
|
|
117
|
+
}
|
|
118
|
+
// --------------
|
|
119
|
+
// add deleted IS_PROTECTED edge on the branch, if necessary
|
|
120
|
+
// --------------
|
|
121
|
+
CALL (rel, latest_deleted_edge, has_protected) {
|
|
122
|
+
WITH *, has_protected
|
|
123
|
+
WHERE has_protected = FALSE
|
|
124
|
+
AND latest_deleted_edge IS NOT NULL
|
|
125
|
+
MERGE (bool:Boolean {value: FALSE})
|
|
126
|
+
CREATE (rel)-[new_edge:IS_PROTECTED]->(bool)
|
|
127
|
+
SET new_edge = properties(latest_deleted_edge)
|
|
128
|
+
}
|
|
129
|
+
"""
|
|
130
|
+
self.add_to_query(query)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class Migration048(ArbitraryMigration):
|
|
134
|
+
"""
|
|
135
|
+
Fix Relationship vertices that are missing IS_VISIBLE and/or IS_PROTECTED edges.
|
|
136
|
+
|
|
137
|
+
This can happen due to a bug in Migration041 that deleted these edges incorrectly.
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
name: str = "048_undelete_rel_props"
|
|
141
|
+
minimum_version: int = 47
|
|
142
|
+
|
|
143
|
+
async def validate_migration(self, db: InfrahubDatabase) -> MigrationResult: # noqa: ARG002
|
|
144
|
+
return MigrationResult()
|
|
145
|
+
|
|
146
|
+
async def execute(self, db: InfrahubDatabase) -> MigrationResult:
|
|
147
|
+
console = get_migration_console()
|
|
148
|
+
|
|
149
|
+
console.log("Deleting duplicate edges for all Relationships", end="...")
|
|
150
|
+
delete_duplicate_edges_query = await DeleteDuplicatedRelationshipEdges.init(
|
|
151
|
+
db=db, migrated_kind_nodes_only=False
|
|
152
|
+
)
|
|
153
|
+
await delete_duplicate_edges_query.execute(db=db)
|
|
154
|
+
console.log("done")
|
|
155
|
+
|
|
156
|
+
console.log("Undeleting Relationship properties", end="...")
|
|
157
|
+
undelete_rel_props_query = await UndeleteRelationshipProperties.init(db=db)
|
|
158
|
+
await undelete_rel_props_query.execute(db=db)
|
|
159
|
+
console.log("done")
|
|
160
|
+
|
|
161
|
+
return MigrationResult()
|
|
@@ -34,7 +34,7 @@ class AttributeKindUpdateMigrationQuery(AttributeMigrationQuery):
|
|
|
34
34
|
// ------------
|
|
35
35
|
// start with all the Attribute vertices we might care about
|
|
36
36
|
// ------------
|
|
37
|
-
MATCH (n:%(
|
|
37
|
+
MATCH (n:%(schema_kinds)s)-[:HAS_ATTRIBUTE]->(attr:Attribute)
|
|
38
38
|
WHERE attr.name = $attr_name
|
|
39
39
|
WITH DISTINCT n, attr
|
|
40
40
|
|
|
@@ -70,7 +70,7 @@ CALL (av_is_default, av_value) {
|
|
|
70
70
|
// ------------
|
|
71
71
|
WITH 1 AS one
|
|
72
72
|
LIMIT 1
|
|
73
|
-
MATCH (n:%(
|
|
73
|
+
MATCH (n:%(schema_kinds)s)-[:HAS_ATTRIBUTE]->(attr:Attribute)
|
|
74
74
|
WHERE attr.name = $attr_name
|
|
75
75
|
WITH DISTINCT n, attr
|
|
76
76
|
|
|
@@ -88,7 +88,6 @@ CALL (n, attr) {
|
|
|
88
88
|
RETURN has_value_e, av
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
|
|
92
91
|
// ------------
|
|
93
92
|
// create and update the HAS_VALUE edges
|
|
94
93
|
// ------------
|
|
@@ -136,7 +135,9 @@ CALL (has_value_e) {
|
|
|
136
135
|
SET has_value_e.to = $at
|
|
137
136
|
}
|
|
138
137
|
""" % {
|
|
139
|
-
"
|
|
138
|
+
"schema_kinds": (
|
|
139
|
+
f"{self.migration.previous_schema.kind}|Profile{self.migration.previous_schema.kind}|Template{self.migration.previous_schema.kind}"
|
|
140
|
+
),
|
|
140
141
|
"branch_filter": branch_filter,
|
|
141
142
|
"new_attr_value_labels": new_attr_value_labels,
|
|
142
143
|
}
|
infrahub/core/query/__init__.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from abc import ABC, abstractmethod
|
|
4
3
|
from collections import defaultdict
|
|
5
4
|
from dataclasses import dataclass, field
|
|
6
5
|
from enum import Enum
|
|
@@ -336,7 +335,7 @@ class QueryStat:
|
|
|
336
335
|
return cls(**data)
|
|
337
336
|
|
|
338
337
|
|
|
339
|
-
class Query
|
|
338
|
+
class Query:
|
|
340
339
|
name: str = "base-query"
|
|
341
340
|
type: QueryType
|
|
342
341
|
|
|
@@ -403,8 +402,12 @@ class Query(ABC):
|
|
|
403
402
|
|
|
404
403
|
return query
|
|
405
404
|
|
|
406
|
-
@abstractmethod
|
|
407
405
|
async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
|
|
406
|
+
# Avoid using this method for new queries and look at migrating older queries. The
|
|
407
|
+
# problem here is that we loose so much information with the `**kwargs` we should instead
|
|
408
|
+
# populate this information via the constructor and anything done within the existing query_init methods
|
|
409
|
+
# could either be handled within __init__ or via dedicated methods within each Query class where appropriate,
|
|
410
|
+
# i.e. things might need to happend in a certain order or we just want to separate the logic better.
|
|
408
411
|
raise NotImplementedError
|
|
409
412
|
|
|
410
413
|
def get_context(self) -> dict[str, str]:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
|
-
from typing import Self
|
|
4
|
+
from typing import Any, Self
|
|
5
5
|
|
|
6
6
|
from pydantic import ConfigDict, Field, model_validator
|
|
7
7
|
|
|
@@ -24,6 +24,33 @@ def get_attribute_parameters_class_for_kind(kind: str) -> type[AttributeParamete
|
|
|
24
24
|
class AttributeParameters(HashableModel):
|
|
25
25
|
model_config = ConfigDict(extra="forbid")
|
|
26
26
|
|
|
27
|
+
@classmethod
|
|
28
|
+
def convert_from(cls, source: AttributeParameters) -> Self:
|
|
29
|
+
"""Convert from another AttributeParameters subclass.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
source: The source AttributeParameters instance to convert from
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
A new instance of the target class with compatible fields populated
|
|
36
|
+
"""
|
|
37
|
+
source_data = source.model_dump()
|
|
38
|
+
return cls.convert_from_dict(source_data=source_data)
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def convert_from_dict(cls, source_data: dict[str, Any]) -> Self:
|
|
42
|
+
"""Convert from a dictionary to the target class.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
source_data: The source dictionary to convert from
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
A new instance of the target class with compatible fields populated
|
|
49
|
+
"""
|
|
50
|
+
target_fields = set(cls.model_fields.keys())
|
|
51
|
+
filtered_data = {k: v for k, v in source_data.items() if k in target_fields}
|
|
52
|
+
return cls(**filtered_data)
|
|
53
|
+
|
|
27
54
|
|
|
28
55
|
class TextAttributeParameters(AttributeParameters):
|
|
29
56
|
regex: str | None = Field(
|
|
@@ -114,13 +114,20 @@ class AttributeSchema(GeneratedAttributeSchema):
|
|
|
114
114
|
@field_validator("parameters", mode="before")
|
|
115
115
|
@classmethod
|
|
116
116
|
def set_parameters_type(cls, value: Any, info: ValidationInfo) -> Any:
|
|
117
|
-
"""Override parameters class if using base AttributeParameters class and should be using a subclass
|
|
117
|
+
"""Override parameters class if using base AttributeParameters class and should be using a subclass.
|
|
118
|
+
|
|
119
|
+
This validator handles parameter type conversion when an attribute's kind changes.
|
|
120
|
+
Fields from the source that don't exist in the target are silently dropped.
|
|
121
|
+
Fields with the same name in both classes are preserved.
|
|
122
|
+
"""
|
|
118
123
|
kind = info.data["kind"]
|
|
119
124
|
expected_parameters_class = get_attribute_parameters_class_for_kind(kind=kind)
|
|
120
125
|
if value is None:
|
|
121
126
|
return expected_parameters_class()
|
|
122
127
|
if not isinstance(value, expected_parameters_class) and isinstance(value, AttributeParameters):
|
|
123
|
-
return expected_parameters_class(
|
|
128
|
+
return expected_parameters_class.convert_from(value)
|
|
129
|
+
if isinstance(value, dict):
|
|
130
|
+
return expected_parameters_class.convert_from_dict(source_data=value)
|
|
124
131
|
return value
|
|
125
132
|
|
|
126
133
|
@model_validator(mode="after")
|
|
@@ -238,19 +245,6 @@ class TextAttributeSchema(AttributeSchema):
|
|
|
238
245
|
json_schema_extra={"update": UpdateSupport.VALIDATE_CONSTRAINT.value},
|
|
239
246
|
)
|
|
240
247
|
|
|
241
|
-
@model_validator(mode="after")
|
|
242
|
-
def reconcile_parameters(self) -> Self:
|
|
243
|
-
if self.regex != self.parameters.regex:
|
|
244
|
-
final_regex = self.parameters.regex if self.parameters.regex is not None else self.regex
|
|
245
|
-
self.regex = self.parameters.regex = final_regex
|
|
246
|
-
if self.min_length != self.parameters.min_length:
|
|
247
|
-
final_min_length = self.parameters.min_length if self.parameters.min_length is not None else self.min_length
|
|
248
|
-
self.min_length = self.parameters.min_length = final_min_length
|
|
249
|
-
if self.max_length != self.parameters.max_length:
|
|
250
|
-
final_max_length = self.parameters.max_length if self.parameters.max_length is not None else self.max_length
|
|
251
|
-
self.max_length = self.parameters.max_length = final_max_length
|
|
252
|
-
return self
|
|
253
|
-
|
|
254
248
|
def get_regex(self) -> str | None:
|
|
255
249
|
return self.parameters.regex
|
|
256
250
|
|
|
@@ -54,7 +54,7 @@ from infrahub.core.schema import (
|
|
|
54
54
|
SchemaRoot,
|
|
55
55
|
TemplateSchema,
|
|
56
56
|
)
|
|
57
|
-
from infrahub.core.schema.attribute_parameters import NumberPoolParameters
|
|
57
|
+
from infrahub.core.schema.attribute_parameters import NumberPoolParameters, TextAttributeParameters
|
|
58
58
|
from infrahub.core.schema.attribute_schema import get_attribute_schema_class_for_kind
|
|
59
59
|
from infrahub.core.schema.definitions.core import core_profile_schema_definition
|
|
60
60
|
from infrahub.core.validators import CONSTRAINT_VALIDATOR_MAP
|
|
@@ -501,11 +501,76 @@ class SchemaBranch:
|
|
|
501
501
|
|
|
502
502
|
return fields or None
|
|
503
503
|
|
|
504
|
+
def _text_attr_needs_reconciliation(self, attr: AttributeSchema) -> bool:
|
|
505
|
+
"""Check if a Text attribute needs reconciliation between deprecated fields and parameters."""
|
|
506
|
+
if not isinstance(attr.parameters, TextAttributeParameters):
|
|
507
|
+
return False
|
|
508
|
+
return (
|
|
509
|
+
attr.regex != attr.parameters.regex
|
|
510
|
+
or attr.min_length != attr.parameters.min_length
|
|
511
|
+
or attr.max_length != attr.parameters.max_length
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
def _reconcile_text_attr(self, attr: AttributeSchema) -> None:
|
|
515
|
+
"""Reconcile a single Text attribute's deprecated fields with parameters.
|
|
516
|
+
|
|
517
|
+
Parameters take precedence over deprecated top-level fields when both are set.
|
|
518
|
+
"""
|
|
519
|
+
if not isinstance(attr.parameters, TextAttributeParameters):
|
|
520
|
+
return
|
|
521
|
+
|
|
522
|
+
# Sync regex: parameters takes precedence
|
|
523
|
+
if attr.parameters.regex is not None:
|
|
524
|
+
attr.regex = attr.parameters.regex
|
|
525
|
+
elif attr.regex is not None:
|
|
526
|
+
attr.parameters.regex = attr.regex
|
|
527
|
+
|
|
528
|
+
# Sync min_length: parameters takes precedence
|
|
529
|
+
if attr.parameters.min_length is not None:
|
|
530
|
+
attr.min_length = attr.parameters.min_length
|
|
531
|
+
elif attr.min_length is not None:
|
|
532
|
+
attr.parameters.min_length = attr.min_length
|
|
533
|
+
|
|
534
|
+
# Sync max_length: parameters takes precedence
|
|
535
|
+
if attr.parameters.max_length is not None:
|
|
536
|
+
attr.max_length = attr.parameters.max_length
|
|
537
|
+
elif attr.max_length is not None:
|
|
538
|
+
attr.parameters.max_length = attr.max_length
|
|
539
|
+
|
|
540
|
+
def _reconcile_text_attribute_parameters(self, schema: SchemaRoot | None = None) -> None:
|
|
541
|
+
"""Reconcile regex, min_length, max_length between deprecated fields and parameters for Text attributes.
|
|
542
|
+
|
|
543
|
+
Args:
|
|
544
|
+
schema: If provided, reconcile incoming schema data before merging.
|
|
545
|
+
If None, reconcile already-loaded schemas (e.g., from database).
|
|
546
|
+
"""
|
|
547
|
+
if schema:
|
|
548
|
+
# Incoming schema: modify in place
|
|
549
|
+
for item in schema.nodes + schema.generics:
|
|
550
|
+
for attr in item.attributes:
|
|
551
|
+
self._reconcile_text_attr(attr)
|
|
552
|
+
return
|
|
553
|
+
|
|
554
|
+
# Loaded schemas: need to duplicate before modifying
|
|
555
|
+
for name in self.all_names:
|
|
556
|
+
node = self.get(name=name, duplicate=False)
|
|
557
|
+
|
|
558
|
+
if not any(self._text_attr_needs_reconciliation(attr) for attr in node.attributes):
|
|
559
|
+
continue
|
|
560
|
+
|
|
561
|
+
node = node.duplicate()
|
|
562
|
+
for attr in node.attributes:
|
|
563
|
+
self._reconcile_text_attr(attr)
|
|
564
|
+
self.set(name=name, schema=node)
|
|
565
|
+
|
|
504
566
|
def load_schema(self, schema: SchemaRoot) -> None:
|
|
505
567
|
"""Load a SchemaRoot object and store all NodeSchema or GenericSchema.
|
|
506
568
|
|
|
507
569
|
In the current implementation, if a schema object present in the SchemaRoot already exist, it will be overwritten.
|
|
508
570
|
"""
|
|
571
|
+
# Reconcile deprecated text attribute parameters before merging
|
|
572
|
+
self._reconcile_text_attribute_parameters(schema)
|
|
573
|
+
|
|
509
574
|
for item in schema.nodes + schema.generics:
|
|
510
575
|
try:
|
|
511
576
|
if item.id:
|
|
@@ -545,6 +610,7 @@ class SchemaBranch:
|
|
|
545
610
|
self.generate_identifiers()
|
|
546
611
|
self.process_default_values()
|
|
547
612
|
self.process_deprecations()
|
|
613
|
+
self._reconcile_text_attribute_parameters()
|
|
548
614
|
self.process_cardinality_counts()
|
|
549
615
|
self.process_inheritance()
|
|
550
616
|
self.process_hierarchy()
|
|
@@ -36,7 +36,7 @@ class AttributeKindUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
|
36
36
|
self.params["null_value"] = NULL_VALUE
|
|
37
37
|
|
|
38
38
|
query = """
|
|
39
|
-
MATCH
|
|
39
|
+
MATCH (n:%(node_kinds)s)
|
|
40
40
|
CALL (n) {
|
|
41
41
|
MATCH path = (root:Root)<-[rr:IS_PART_OF]-(n)-[ra:HAS_ATTRIBUTE]-(:Attribute { name: $attr_name } )-[rv:HAS_VALUE]-(av:AttributeValue)
|
|
42
42
|
WHERE all(
|
|
@@ -51,7 +51,10 @@ class AttributeKindUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
|
51
51
|
WHERE all(r in relationships(full_path) WHERE r.status = "active")
|
|
52
52
|
AND attribute_value IS NOT NULL
|
|
53
53
|
AND attribute_value <> $null_value
|
|
54
|
-
""" % {
|
|
54
|
+
""" % {
|
|
55
|
+
"branch_filter": branch_filter,
|
|
56
|
+
"node_kinds": f"{self.node_schema.kind}|Profile{self.node_schema.kind}|Template{self.node_schema.kind}",
|
|
57
|
+
}
|
|
55
58
|
|
|
56
59
|
self.add_to_query(query)
|
|
57
60
|
self.return_labels = ["node.uuid", "attribute_value", "value_relationship.branch as value_branch"]
|
infrahub/graphql/app.py
CHANGED
|
@@ -172,9 +172,9 @@ class InfrahubGraphQLApp:
|
|
|
172
172
|
|
|
173
173
|
response = handler(request)
|
|
174
174
|
if isawaitable(response):
|
|
175
|
-
return await
|
|
175
|
+
return await response
|
|
176
176
|
|
|
177
|
-
return
|
|
177
|
+
return response
|
|
178
178
|
|
|
179
179
|
async def _handle_http_request(
|
|
180
180
|
self, request: Request, db: InfrahubDatabase, branch: Branch, account_session: AccountSession
|
|
@@ -60,10 +60,10 @@ class ConflictDetails(ObjectType):
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
class DiffSummaryCounts(ObjectType):
|
|
63
|
-
num_added = Int(required=
|
|
64
|
-
num_updated = Int(required=
|
|
65
|
-
num_removed = Int(required=
|
|
66
|
-
num_conflicts = Int(required=
|
|
63
|
+
num_added = Int(required=True)
|
|
64
|
+
num_updated = Int(required=True)
|
|
65
|
+
num_removed = Int(required=True)
|
|
66
|
+
num_conflicts = Int(required=True)
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
class DiffProperty(ObjectType):
|
|
@@ -146,7 +146,7 @@ class DiffTreeSummary(DiffSummaryCounts):
|
|
|
146
146
|
diff_branch = String(required=True)
|
|
147
147
|
from_time = DateTime(required=True)
|
|
148
148
|
to_time = DateTime(required=True)
|
|
149
|
-
num_unchanged = Int(required=
|
|
149
|
+
num_unchanged = Int(required=True)
|
|
150
150
|
num_untracked_base_changes = Int(required=False)
|
|
151
151
|
num_untracked_diff_changes = Int(required=False)
|
|
152
152
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: infrahub-server
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.3
|
|
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
|
Project-URL: Homepage, https://opsmill.com
|
|
6
6
|
Project-URL: Repository, https://github.com/opsmill/infrahub
|
|
@@ -79,7 +79,7 @@ infrahub/constants/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
|
|
|
79
79
|
infrahub/constants/database.py,sha256=p0Ga54CQLnjziSWmLRDzdUUBJs2ImPWPyPPozofmGhI,502
|
|
80
80
|
infrahub/constants/environment.py,sha256=ry-6qsBzSumOjjiq1D3XNoquf1LWqFKiQSJj8t6nET4,32
|
|
81
81
|
infrahub/core/__init__.py,sha256=z6EJBZyCYCBqinoBtX9li6BTBbbGV8WCkE_4CrEsmDA,104
|
|
82
|
-
infrahub/core/account.py,sha256=
|
|
82
|
+
infrahub/core/account.py,sha256=uXr12tcA6rqufAb0FGgd68y3W79qqlDxnkSonazt4Mc,27470
|
|
83
83
|
infrahub/core/attribute.py,sha256=quW5lG-e4c3VjIhiSta12TUTB8Uv_Gmi8mwTenwBSIo,44921
|
|
84
84
|
infrahub/core/enums.py,sha256=qGbhRVoH43Xi0iDkUfWdQiKapJbLT9UKsCobFk_paIk,491
|
|
85
85
|
infrahub/core/initialization.py,sha256=MuhZR6VDFfEiQw_ZPm-LBcBQmpvEdaxovGWtx_YKtVc,22081
|
|
@@ -98,7 +98,7 @@ infrahub/core/branch/__init__.py,sha256=h0oIj0gHp1xI-N1cYW8_N6VZ81CBOmLuiUt5cS5n
|
|
|
98
98
|
infrahub/core/branch/enums.py,sha256=wE_TvKxd-r3zeHgLOMuZhsyKRwDWWC8BMxAEC_aX7A8,212
|
|
99
99
|
infrahub/core/branch/models.py,sha256=NWbDbK5EjwafopEtiZVzArvxpZKHC8RcWPDyHmYZTcg,21268
|
|
100
100
|
infrahub/core/branch/needs_rebase_status.py,sha256=purrg93k9zWcV9NONjIdMF8cWLXEKHq6YjO0ayC3C04,407
|
|
101
|
-
infrahub/core/branch/tasks.py,sha256=
|
|
101
|
+
infrahub/core/branch/tasks.py,sha256=Z5hYlhsUR2NRz2BJx-2E4f3nEesK4aFJYtpTjVCvybs,23804
|
|
102
102
|
infrahub/core/changelog/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
103
103
|
infrahub/core/changelog/diff.py,sha256=0BxCpsgJ-38x5BBz5XDtAvc9FPy82M0NlzXl8nQ-c70,13752
|
|
104
104
|
infrahub/core/changelog/models.py,sha256=pA8Tvq37ia58rGZjFb6OWXIH974J43s3_LG9VEvt-tw,29832
|
|
@@ -171,7 +171,7 @@ infrahub/core/diff/query/update_conflict_query.py,sha256=kQkFazz88wnApr8UU_qb0ru
|
|
|
171
171
|
infrahub/core/diff/repository/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
172
172
|
infrahub/core/diff/repository/deserializer.py,sha256=bhN9ao8HxqKyRz273QGLNV9z9_SS4EQnM9JoY5ptx78,21337
|
|
173
173
|
infrahub/core/diff/repository/repository.py,sha256=u0QTMY1e2dknG_DuRAwzFt-Lp1_mdj5lqF2ymt77k9E,25581
|
|
174
|
-
infrahub/core/graph/__init__.py,sha256=
|
|
174
|
+
infrahub/core/graph/__init__.py,sha256=uSqGhFuXphIN54hyFRnktc-l81hPHwfKpgNgI5_amKQ,19
|
|
175
175
|
infrahub/core/graph/constraints.py,sha256=ePTN1FtvTX01R1CcnYDNDGwC82YyIIux2_Jnf0e0PeI,10397
|
|
176
176
|
infrahub/core/graph/index.py,sha256=A9jzEE_wldBJsEsflODeMt4GM8sPmmbHAJRNdFioR1k,1736
|
|
177
177
|
infrahub/core/graph/schema.py,sha256=o50Jcy6GBRk55RkDJSMIDDwHhLD7y_RWOirI9rCex4A,10776
|
|
@@ -190,7 +190,7 @@ infrahub/core/migrations/__init__.py,sha256=ttA1YkKhiG9Zc0fwIIcMLIDCrIhN5xVOIh6o
|
|
|
190
190
|
infrahub/core/migrations/exceptions.py,sha256=gEAkWzjvN-IXr0YPqUrEqnu_GsR-uqucsu1QUaWhEmM,147
|
|
191
191
|
infrahub/core/migrations/runner.py,sha256=d_HxhO1RRh3Ec7cG5Z8SKV2X0mqc4J5Y9UZwHb4d6Co,2145
|
|
192
192
|
infrahub/core/migrations/shared.py,sha256=eP-OltT87Aw0I5MLm90YZ50iwxbNbC229eO8HPwC7kc,9575
|
|
193
|
-
infrahub/core/migrations/graph/__init__.py,sha256=
|
|
193
|
+
infrahub/core/migrations/graph/__init__.py,sha256=5q-xHmDCWGIrbAZVIn2TlgzNMk0NURJQjoVtON042Sc,4706
|
|
194
194
|
infrahub/core/migrations/graph/load_schema_branch.py,sha256=OvjowaeDnx4djD1aGPjE7Rqyh1p843LSodOf_Frdt9U,1008
|
|
195
195
|
infrahub/core/migrations/graph/m001_add_version_to_graph.py,sha256=YcLN6cFjE6IGheXR4Ujb6CcyY8bJ7WE289hcKJaENOc,1515
|
|
196
196
|
infrahub/core/migrations/graph/m002_attribute_is_default.py,sha256=wB6f2N_ChTvGajqHD-OWCG5ahRMDhhXZuwo79ieq_II,1036
|
|
@@ -232,13 +232,14 @@ infrahub/core/migrations/graph/m037_index_attr_vals.py,sha256=pc-223N-jhAglpPIeU
|
|
|
232
232
|
infrahub/core/migrations/graph/m038_redo_0000_prefix_fix.py,sha256=8seWnXQhgEJDFLWxYHVcnMNDPcHq5C24c0RYrtn_WGE,2411
|
|
233
233
|
infrahub/core/migrations/graph/m039_ipam_reconcile.py,sha256=yRWTE73Rq1Qh6tPLu98w60zJdx8cgdO7_DL-g10x87s,11112
|
|
234
234
|
infrahub/core/migrations/graph/m040_duplicated_attributes.py,sha256=2LxsG-CfcZnBirwGhwYL4kU-g3oxl6lNSM12vZTZ7Gw,2930
|
|
235
|
-
infrahub/core/migrations/graph/m041_deleted_dup_edges.py,sha256=
|
|
235
|
+
infrahub/core/migrations/graph/m041_deleted_dup_edges.py,sha256=ydQ73MuhCNhl8cDrZ5N_jCP5vFCUIQTlJTGiTHMQVeM,5911
|
|
236
236
|
infrahub/core/migrations/graph/m042_profile_attrs_in_db.py,sha256=KdEaNPHovJxxiNL3CFRjWBnNzaMdidj1nmW5Jbhrt-4,6431
|
|
237
237
|
infrahub/core/migrations/graph/m043_create_hfid_display_label_in_db.py,sha256=giICX6Dwd_z1GaWTWyX3KD5Va34LGth0Vv2uyaof044,7290
|
|
238
238
|
infrahub/core/migrations/graph/m044_backfill_hfid_display_label_in_db.py,sha256=FuV3EBWS4lY4dtOn7-1Qgo6J7j4XDq4s5yIQjfCCVDM,39575
|
|
239
239
|
infrahub/core/migrations/graph/m045_backfill_hfid_display_label_in_db_profile_template.py,sha256=mnND7TIdPSVcN9uJeYMmRpVjlAU6QBqfu7e1CS31D9Q,7934
|
|
240
240
|
infrahub/core/migrations/graph/m046_fill_agnostic_hfid_display_labels.py,sha256=labPu3UwH2L6X3VCVmNQHGSbRS-De0ihVzsaUiTf2so,10210
|
|
241
241
|
infrahub/core/migrations/graph/m047_backfill_or_null_display_label.py,sha256=0ZrkeYWKhWERGOg_IH74KNuJtV8bR0bw1jOEkeZBFtE,24328
|
|
242
|
+
infrahub/core/migrations/graph/m048_undelete_rel_props.py,sha256=6xlWsWtzzDwtyGmdRGKZa3hCpt-mp5QX7hNeJMnw3NM,5647
|
|
242
243
|
infrahub/core/migrations/query/__init__.py,sha256=nUbKk8bX6Ei4RkLe0VNNAm7c-d2zDoAMgdFGkYW0Czw,850
|
|
243
244
|
infrahub/core/migrations/query/attribute_add.py,sha256=wKChMnqcd8hb8YCTIU3rUrtVqwHFSI5bdvXAPUcnRIA,4969
|
|
244
245
|
infrahub/core/migrations/query/attribute_remove.py,sha256=IhAPlv9jyZTWMf8f8HZJ8G0ImWebt-ER78NrP3vIWhU,5307
|
|
@@ -248,7 +249,7 @@ infrahub/core/migrations/query/node_duplicate.py,sha256=yaxeZBYd52jgEB5XY1PZxksT
|
|
|
248
249
|
infrahub/core/migrations/query/relationship_duplicate.py,sha256=hjUFjNqhaFc2tEg79BXR2xDr_4Wdmu9fVF02cTEICTk,7319
|
|
249
250
|
infrahub/core/migrations/query/schema_attribute_update.py,sha256=fLclNEgoikO_ddlFEo1ts-dZwTXITA85kdJ00fXFxqo,3382
|
|
250
251
|
infrahub/core/migrations/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
251
|
-
infrahub/core/migrations/schema/attribute_kind_update.py,sha256=
|
|
252
|
+
infrahub/core/migrations/schema/attribute_kind_update.py,sha256=hCu7LP8hS_LMv9zHmByb_gFEm1xcN_wREkuO1qDWJf4,6453
|
|
252
253
|
infrahub/core/migrations/schema/attribute_name_update.py,sha256=gebaeQX1MLmOxupTPcCzLJdeEQlUzs3XIl7T15-RdXY,1595
|
|
253
254
|
infrahub/core/migrations/schema/attribute_supports_profile.py,sha256=xEmLV1Km-GOpvUAia0izN9VWERveSGcikb0AHbuFs5g,3465
|
|
254
255
|
infrahub/core/migrations/schema/models.py,sha256=F1yp0GM-HutGdzhE0uPFq9JCTH9iHM3V4iDm2e2c4YU,1357
|
|
@@ -276,7 +277,7 @@ infrahub/core/node/resource_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQ
|
|
|
276
277
|
infrahub/core/node/resource_manager/ip_address_pool.py,sha256=pJa3peul-sNNN_tNNsMn8TB6Jp8cbuh4xwrIf6-3Nd0,5265
|
|
277
278
|
infrahub/core/node/resource_manager/ip_prefix_pool.py,sha256=z1CY7OM41p-X3dJcuGu7coDHDoGHvnB4puvmmleVmrU,5527
|
|
278
279
|
infrahub/core/node/resource_manager/number_pool.py,sha256=KaDxJdIspQ_riXcDGn6RSBDltxEIonmoj68vsQvhFwE,5829
|
|
279
|
-
infrahub/core/query/__init__.py,sha256=
|
|
280
|
+
infrahub/core/query/__init__.py,sha256=XPnVyuCQ-Vf5f6yZGZ4Foe2P-CW4DiIC3XECxMRVwmY,23557
|
|
280
281
|
infrahub/core/query/attribute.py,sha256=eHrxXo-5YV4oUOx9kaU0rMKv-9lCRcqz2PMWNtqPuUM,14867
|
|
281
282
|
infrahub/core/query/branch.py,sha256=yZ7lasZ06-F0P7t_l40GFWM_JP1q_6_IxRhiVxvEG4o,4809
|
|
282
283
|
infrahub/core/query/delete.py,sha256=7tPP1qtNV6QGYtmgE1RKsuQ9oxENnMTVkttLvJ2PiKg,1927
|
|
@@ -300,8 +301,8 @@ infrahub/core/relationship/constraints/peer_parent.py,sha256=z7elpC8xS_ovAF28Haq
|
|
|
300
301
|
infrahub/core/relationship/constraints/peer_relatives.py,sha256=Ye79l7njaWxZkU2chTOaptIjvKBIawsNCl0IQxCTDtM,2737
|
|
301
302
|
infrahub/core/relationship/constraints/profiles_kind.py,sha256=nEZPGtGcmelZ1Nb8EPcQ-7_zCLCNIYwwWbU6C9fLj5E,2464
|
|
302
303
|
infrahub/core/schema/__init__.py,sha256=_vOy96uKjAxj8nvTR0qzHcnIYUzdVAAcUIk2kyUKjCQ,6641
|
|
303
|
-
infrahub/core/schema/attribute_parameters.py,sha256=
|
|
304
|
-
infrahub/core/schema/attribute_schema.py,sha256=
|
|
304
|
+
infrahub/core/schema/attribute_parameters.py,sha256=EMkjs7x0Rakxqu-ckXJ0VZCPzRGrRt2DBoKX6OWrJWM,7477
|
|
305
|
+
infrahub/core/schema/attribute_schema.py,sha256=1DVEwFnHYq08cyehJA3dl5-p8cSoBXaR2YECXqxkWXM,10049
|
|
305
306
|
infrahub/core/schema/basenode_schema.py,sha256=Se-pEYgnL2Y6_OSMZrl5BWgW9taBaBaqddL2NoXfArE,29765
|
|
306
307
|
infrahub/core/schema/computed_attribute.py,sha256=9rznZJpGqX8fxLx0EguPmww8LoHsadMtQQUKaMoJPcI,1809
|
|
307
308
|
infrahub/core/schema/constants.py,sha256=KtFrvwNckyKZSGIMD4XfxI5eFTZqBRiw54R7BE5h39Q,374
|
|
@@ -311,7 +312,7 @@ infrahub/core/schema/manager.py,sha256=Zz1kRc5g_-1U5xlj6kuOG1ltnpntkkbyMQeP1z0we
|
|
|
311
312
|
infrahub/core/schema/node_schema.py,sha256=W2Jx5QXrQ5ygUEyTKnIHhj6Xe7jJ6Y-iQArEo05cWRI,6341
|
|
312
313
|
infrahub/core/schema/profile_schema.py,sha256=sV4lp1UyBye12M7BJcA2obb4tx3M9J5P89SLqkmFxJY,1237
|
|
313
314
|
infrahub/core/schema/relationship_schema.py,sha256=ryCvmUQl3HBo_Sk07Xl5rT48PPuhlBkYRmm-lSdfJPI,8445
|
|
314
|
-
infrahub/core/schema/schema_branch.py,sha256=
|
|
315
|
+
infrahub/core/schema/schema_branch.py,sha256=IsD8NZ9454ohju_Wp-2n2amtjw1GDuRx_dgc0c3CTzA,123061
|
|
315
316
|
infrahub/core/schema/schema_branch_computed.py,sha256=14UUsQJDLMHkYhg7QMqeLiTF3PO8c8rGa90ul3F2ZZo,10629
|
|
316
317
|
infrahub/core/schema/schema_branch_display.py,sha256=bvXVSZZC1uilBicTXeUdrPkxIVuIIY0aLjkJQkvrTbY,6098
|
|
317
318
|
infrahub/core/schema/schema_branch_hfid.py,sha256=XcNV2nNbpOhif5HHN6wvXXuM-nY8eMWhlidr4g8riro,5276
|
|
@@ -358,7 +359,7 @@ infrahub/core/validators/tasks.py,sha256=Qb9q2l55NKhvWXCrZclVWvJhzsN3yniN7nsYqUL
|
|
|
358
359
|
infrahub/core/validators/attribute/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
359
360
|
infrahub/core/validators/attribute/choices.py,sha256=Zt_iy6g2ANK4wBOgWqnhvU0dZ2ZYGvyhu93t7eNwj8Q,5380
|
|
360
361
|
infrahub/core/validators/attribute/enum.py,sha256=3PzkYUuzbt8NqRH4IP4cMjoDxzUvJzbNYC5ZpW5zKZQ,4161
|
|
361
|
-
infrahub/core/validators/attribute/kind.py,sha256=
|
|
362
|
+
infrahub/core/validators/attribute/kind.py,sha256=nJFV9Dh164013_8AtMCEZvo5TH7r4L15IaPsTqqBC-E,4712
|
|
362
363
|
infrahub/core/validators/attribute/length.py,sha256=H0nP2x2ynzcbMnc6neIje01wXipbt8Wr49iNTqIvWxI,4526
|
|
363
364
|
infrahub/core/validators/attribute/min_max.py,sha256=3x6iCJuVdt3vim6wPaF4Bar8RlR3FhJu3DYQiR2GZRI,5661
|
|
364
365
|
infrahub/core/validators/attribute/number_pool.py,sha256=edWmpHbme9YqWxeZJ5V0dvTCyIqLFyej2YNTyM-Emq4,4709
|
|
@@ -488,7 +489,7 @@ infrahub/git_credential/askpass.py,sha256=BL7e4Xkx5la7XFk-GQR6MXxV5B29Mzb5ZnVnlj
|
|
|
488
489
|
infrahub/git_credential/helper.py,sha256=cwSMKRTgqrqIBM66jEOtlj4MMLf647KJWmtnnVxFtTY,2337
|
|
489
490
|
infrahub/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
490
491
|
infrahub/graphql/analyzer.py,sha256=2-C1Wli0fXpXTVvNtP7IxiKWBJN97lqOeEP2L0oy3ho,30944
|
|
491
|
-
infrahub/graphql/app.py,sha256=
|
|
492
|
+
infrahub/graphql/app.py,sha256=5BudFFwmV0LJizN0m4Cioe5-DbpTp5-QxHUhwlPIHpk,21139
|
|
492
493
|
infrahub/graphql/constants.py,sha256=iVvo3HK-ch7YmHw1Eg2E_ja3I45cNAwjpYahsnu85CI,37
|
|
493
494
|
infrahub/graphql/context.py,sha256=ahp-MvX_0glg9mSPbPVhEwvbYzrIKtaEAGt7CVnAusE,1681
|
|
494
495
|
infrahub/graphql/directives.py,sha256=wyIkJFp7l0J4JqNl1Lqu7YfKXP7glrewlQFMDTUAPcE,645
|
|
@@ -566,7 +567,7 @@ infrahub/graphql/queries/search.py,sha256=22MCNHMHrc0C6MjMSNxzIdnDUug-Gp2NGtO4qP
|
|
|
566
567
|
infrahub/graphql/queries/status.py,sha256=BSCBT4abaswlfh7JZB8mk_rR-6FXIx-wxQA_YwiWvI4,2124
|
|
567
568
|
infrahub/graphql/queries/task.py,sha256=UG9Ur2CH5GOmfyk34ItqAPuCEkqIhdU-G1n6C3iK_lc,3921
|
|
568
569
|
infrahub/graphql/queries/diff/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
569
|
-
infrahub/graphql/queries/diff/tree.py,sha256=
|
|
570
|
+
infrahub/graphql/queries/diff/tree.py,sha256=nCnjQbCP6VzV8ZEO62NYa5_Eiz9Pd-KAC9ms6gmqkUs,25251
|
|
570
571
|
infrahub/graphql/resolvers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
571
572
|
infrahub/graphql/resolvers/ipam.py,sha256=kGrr5X6nseA-N8UCK9Hh2V-U3txyL3wIX7oQYJ7oi-U,17625
|
|
572
573
|
infrahub/graphql/resolvers/many_relationship.py,sha256=ECWGpRUG22kvY6BkxCMNYex_ZaJopuEWgejGHD28wVY,9743
|
|
@@ -887,8 +888,8 @@ infrahub_testcontainers/models.py,sha256=hT7WEX2o7gxTFPE9uhtP5yigKgP5YSsy2c3tFB-
|
|
|
887
888
|
infrahub_testcontainers/performance_test.py,sha256=_nf7Uk15mHwqpN4y7XUfI4JI54-UaXW-Yu4uwMIx21w,6185
|
|
888
889
|
infrahub_testcontainers/plugin.py,sha256=I3RuZQ0dARyKHuqCf0y1Yj731P2Mwf3BJUehRJKeWrs,5645
|
|
889
890
|
infrahub_testcontainers/prometheus.yml,sha256=610xQEyj3xuVJMzPkC4m1fRnCrjGpiRBrXA2ytCLa54,599
|
|
890
|
-
infrahub_server-1.6.
|
|
891
|
-
infrahub_server-1.6.
|
|
892
|
-
infrahub_server-1.6.
|
|
893
|
-
infrahub_server-1.6.
|
|
894
|
-
infrahub_server-1.6.
|
|
891
|
+
infrahub_server-1.6.3.dist-info/METADATA,sha256=LbmpeUrNY4vGz6V7ngsWfSHfvseeQGWjw94Cap_4ziQ,5898
|
|
892
|
+
infrahub_server-1.6.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
893
|
+
infrahub_server-1.6.3.dist-info/entry_points.txt,sha256=_xSAw1Wp-GslD95j4FESCxU1H7G7B9b42zp8-LAmC8Q,406
|
|
894
|
+
infrahub_server-1.6.3.dist-info/licenses/LICENSE.txt,sha256=7GQO7kxVoQYnZtFrjZBKLRXbrGwwwimHPPOJtqXsozQ,11340
|
|
895
|
+
infrahub_server-1.6.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|