infrahub-server 1.2.11__py3-none-any.whl → 1.3.0b1__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 +86 -0
- infrahub/actions/gather.py +114 -0
- infrahub/actions/models.py +241 -0
- infrahub/actions/parsers.py +104 -0
- infrahub/actions/schema.py +382 -0
- infrahub/actions/tasks.py +126 -0
- infrahub/actions/triggers.py +21 -0
- infrahub/cli/db.py +1 -2
- infrahub/core/account.py +24 -47
- infrahub/core/attribute.py +13 -15
- infrahub/core/constants/__init__.py +5 -0
- infrahub/core/constants/infrahubkind.py +9 -0
- infrahub/core/convert_object_type/__init__.py +0 -0
- infrahub/core/convert_object_type/conversion.py +122 -0
- infrahub/core/convert_object_type/schema_mapping.py +56 -0
- infrahub/core/diff/query/all_conflicts.py +1 -5
- infrahub/core/diff/query/artifact.py +10 -20
- infrahub/core/diff/query/diff_get.py +3 -6
- infrahub/core/diff/query/field_summary.py +2 -4
- infrahub/core/diff/query/merge.py +70 -123
- infrahub/core/diff/query/save.py +20 -32
- infrahub/core/diff/query/summary_counts_enricher.py +34 -54
- infrahub/core/manager.py +14 -11
- infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -4
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +11 -22
- infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -6
- infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +1 -2
- infrahub/core/migrations/graph/m024_missing_hierarchy_backfill.py +1 -2
- infrahub/core/migrations/query/attribute_add.py +1 -2
- infrahub/core/migrations/query/attribute_rename.py +5 -10
- infrahub/core/migrations/query/delete_element_in_schema.py +19 -17
- infrahub/core/migrations/query/node_duplicate.py +19 -21
- infrahub/core/migrations/query/relationship_duplicate.py +19 -17
- infrahub/core/migrations/schema/node_attribute_remove.py +4 -8
- infrahub/core/migrations/schema/node_remove.py +19 -19
- infrahub/core/models.py +29 -2
- infrahub/core/node/__init__.py +90 -18
- infrahub/core/node/create.py +211 -0
- infrahub/core/node/resource_manager/number_pool.py +31 -5
- infrahub/core/node/standard.py +6 -1
- infrahub/core/protocols.py +56 -0
- infrahub/core/protocols_base.py +3 -0
- infrahub/core/query/__init__.py +2 -2
- infrahub/core/query/diff.py +19 -32
- infrahub/core/query/ipam.py +10 -20
- infrahub/core/query/node.py +28 -46
- infrahub/core/query/relationship.py +53 -32
- infrahub/core/query/resource_manager.py +1 -2
- infrahub/core/query/subquery.py +2 -4
- infrahub/core/relationship/model.py +3 -0
- infrahub/core/schema/__init__.py +2 -1
- infrahub/core/schema/attribute_parameters.py +160 -0
- infrahub/core/schema/attribute_schema.py +111 -8
- infrahub/core/schema/basenode_schema.py +25 -1
- infrahub/core/schema/definitions/core/__init__.py +29 -1
- infrahub/core/schema/definitions/core/group.py +45 -0
- infrahub/core/schema/definitions/internal.py +27 -4
- infrahub/core/schema/generated/attribute_schema.py +16 -3
- infrahub/core/schema/manager.py +3 -0
- infrahub/core/schema/schema_branch.py +67 -7
- infrahub/core/validators/__init__.py +13 -1
- infrahub/core/validators/attribute/choices.py +1 -3
- infrahub/core/validators/attribute/enum.py +1 -3
- infrahub/core/validators/attribute/kind.py +1 -3
- infrahub/core/validators/attribute/length.py +13 -7
- infrahub/core/validators/attribute/min_max.py +118 -0
- infrahub/core/validators/attribute/number_pool.py +106 -0
- infrahub/core/validators/attribute/optional.py +1 -4
- infrahub/core/validators/attribute/regex.py +5 -6
- infrahub/core/validators/attribute/unique.py +1 -3
- infrahub/core/validators/determiner.py +18 -2
- infrahub/core/validators/enum.py +12 -0
- infrahub/core/validators/node/hierarchy.py +3 -6
- infrahub/core/validators/query.py +1 -3
- infrahub/core/validators/relationship/count.py +6 -12
- infrahub/core/validators/relationship/optional.py +2 -4
- infrahub/core/validators/relationship/peer.py +3 -8
- infrahub/core/validators/uniqueness/query.py +5 -9
- infrahub/database/__init__.py +11 -2
- infrahub/events/group_action.py +1 -0
- infrahub/git/base.py +5 -3
- infrahub/git/integrator.py +102 -3
- infrahub/graphql/analyzer.py +139 -18
- infrahub/graphql/manager.py +4 -0
- infrahub/graphql/mutations/action.py +164 -0
- infrahub/graphql/mutations/convert_object_type.py +62 -0
- infrahub/graphql/mutations/main.py +24 -175
- infrahub/graphql/mutations/proposed_change.py +20 -17
- infrahub/graphql/mutations/resource_manager.py +62 -6
- infrahub/graphql/queries/convert_object_type_mapping.py +36 -0
- infrahub/graphql/queries/resource_manager.py +7 -1
- infrahub/graphql/schema.py +6 -0
- infrahub/menu/menu.py +31 -0
- infrahub/message_bus/messages/__init__.py +0 -10
- infrahub/message_bus/operations/__init__.py +0 -8
- infrahub/patch/queries/consolidate_duplicated_nodes.py +3 -6
- infrahub/patch/queries/delete_duplicated_edges.py +5 -10
- infrahub/pools/number.py +5 -3
- infrahub/prefect_server/models.py +1 -19
- infrahub/proposed_change/models.py +68 -3
- infrahub/proposed_change/tasks.py +907 -30
- infrahub/task_manager/models.py +10 -6
- infrahub/trigger/catalogue.py +2 -0
- infrahub/trigger/models.py +18 -2
- infrahub/trigger/tasks.py +3 -1
- infrahub/types.py +6 -0
- infrahub/workflows/catalogue.py +76 -0
- infrahub_sdk/client.py +43 -10
- infrahub_sdk/node/__init__.py +39 -0
- infrahub_sdk/node/attribute.py +122 -0
- infrahub_sdk/node/constants.py +21 -0
- infrahub_sdk/{node.py → node/node.py} +50 -749
- infrahub_sdk/node/parsers.py +15 -0
- infrahub_sdk/node/property.py +24 -0
- infrahub_sdk/node/related_node.py +266 -0
- infrahub_sdk/node/relationship.py +302 -0
- infrahub_sdk/protocols.py +112 -0
- infrahub_sdk/protocols_base.py +34 -2
- infrahub_sdk/query_groups.py +13 -2
- infrahub_sdk/schema/main.py +1 -0
- infrahub_sdk/schema/repository.py +16 -0
- infrahub_sdk/spec/object.py +1 -1
- infrahub_sdk/store.py +1 -1
- infrahub_sdk/testing/schemas/car_person.py +1 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/METADATA +4 -4
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/RECORD +134 -122
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/WHEEL +1 -1
- infrahub_testcontainers/container.py +0 -1
- infrahub_testcontainers/docker-compose.test.yml +1 -1
- infrahub_testcontainers/helpers.py +8 -2
- infrahub/message_bus/messages/check_generator_run.py +0 -26
- infrahub/message_bus/messages/finalize_validator_execution.py +0 -15
- infrahub/message_bus/messages/proposed_change/base_with_diff.py +0 -16
- infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +0 -11
- infrahub/message_bus/messages/request_generatordefinition_check.py +0 -20
- infrahub/message_bus/messages/request_proposedchange_pipeline.py +0 -23
- infrahub/message_bus/operations/check/__init__.py +0 -3
- infrahub/message_bus/operations/check/generator.py +0 -156
- infrahub/message_bus/operations/finalize/__init__.py +0 -3
- infrahub/message_bus/operations/finalize/validator.py +0 -133
- infrahub/message_bus/operations/requests/__init__.py +0 -9
- infrahub/message_bus/operations/requests/generator_definition.py +0 -140
- infrahub/message_bus/operations/requests/proposed_change.py +0 -629
- /infrahub/{message_bus/messages/proposed_change → actions}/__init__.py +0 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -55,7 +55,6 @@ class DeleteElementInSchemaQuery(Query):
|
|
|
55
55
|
@staticmethod
|
|
56
56
|
def _render_sub_query_per_rel_type(rel_name: str, rel_type: str, direction: GraphRelDirection) -> str:
|
|
57
57
|
subquery = [
|
|
58
|
-
f"WITH peer_node, {rel_name}, element_to_delete",
|
|
59
58
|
f"WITH peer_node, {rel_name}, element_to_delete",
|
|
60
59
|
f'WHERE type({rel_name}) = "{rel_type}"',
|
|
61
60
|
]
|
|
@@ -67,28 +66,32 @@ class DeleteElementInSchemaQuery(Query):
|
|
|
67
66
|
return "\n".join(subquery)
|
|
68
67
|
|
|
69
68
|
@classmethod
|
|
70
|
-
def _render_sub_query_out(cls) -> str:
|
|
69
|
+
def _render_sub_query_out(cls) -> tuple[str, str]:
|
|
70
|
+
rel_name = "rel_outband"
|
|
71
|
+
sub_query_out_args = f"peer_node, {rel_name}, element_to_delete"
|
|
71
72
|
sub_queries_out = [
|
|
72
73
|
cls._render_sub_query_per_rel_type(
|
|
73
|
-
rel_name=
|
|
74
|
+
rel_name=rel_name, rel_type=rel_type, direction=GraphRelDirection.OUTBOUND
|
|
74
75
|
)
|
|
75
76
|
for rel_type, rel_def in GraphNodeRelationships.model_fields.items()
|
|
76
77
|
if rel_def.default.direction in [GraphRelDirection.OUTBOUND, GraphRelDirection.EITHER]
|
|
77
78
|
]
|
|
78
79
|
sub_query_out = "\nUNION\n".join(sub_queries_out)
|
|
79
|
-
return sub_query_out
|
|
80
|
+
return sub_query_out, sub_query_out_args
|
|
80
81
|
|
|
81
82
|
@classmethod
|
|
82
|
-
def _render_sub_query_in(cls) -> str:
|
|
83
|
+
def _render_sub_query_in(cls) -> tuple[str, str]:
|
|
84
|
+
rel_name = "rel_inband"
|
|
85
|
+
sub_query_in_args = f"peer_node, {rel_name}, element_to_delete"
|
|
83
86
|
sub_queries_in = [
|
|
84
87
|
cls._render_sub_query_per_rel_type(
|
|
85
|
-
rel_name=
|
|
88
|
+
rel_name=rel_name, rel_type=rel_type, direction=GraphRelDirection.INBOUND
|
|
86
89
|
)
|
|
87
90
|
for rel_type, rel_def in GraphNodeRelationships.model_fields.items()
|
|
88
91
|
if rel_def.default.direction in [GraphRelDirection.INBOUND, GraphRelDirection.EITHER]
|
|
89
92
|
]
|
|
90
93
|
sub_query_in = "\nUNION\n".join(sub_queries_in)
|
|
91
|
-
return sub_query_in
|
|
94
|
+
return sub_query_in, sub_query_in_args
|
|
92
95
|
|
|
93
96
|
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
94
97
|
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
|
|
@@ -108,16 +111,15 @@ class DeleteElementInSchemaQuery(Query):
|
|
|
108
111
|
"from": self.at.to_string(),
|
|
109
112
|
}
|
|
110
113
|
|
|
111
|
-
sub_query_out = self._render_sub_query_out()
|
|
112
|
-
sub_query_in = self._render_sub_query_in()
|
|
114
|
+
sub_query_out, sub_query_out_args = self._render_sub_query_out()
|
|
115
|
+
sub_query_in, sub_query_in_args = self._render_sub_query_in()
|
|
113
116
|
|
|
114
117
|
self.add_to_query(self.render_match())
|
|
115
118
|
self.add_to_query(self.render_where())
|
|
116
119
|
|
|
117
120
|
# ruff: noqa: E501
|
|
118
121
|
query = """
|
|
119
|
-
CALL {
|
|
120
|
-
WITH attr_node
|
|
122
|
+
CALL (attr_node) {
|
|
121
123
|
MATCH (root:Root)<-[r:IS_PART_OF]-(attr_node)
|
|
122
124
|
WHERE %(branch_filter)s
|
|
123
125
|
RETURN attr_node as n1, r as r1
|
|
@@ -130,8 +132,7 @@ class DeleteElementInSchemaQuery(Query):
|
|
|
130
132
|
|
|
131
133
|
// Process Outbound Relationship
|
|
132
134
|
MATCH (element_to_delete)-[]->(peer)
|
|
133
|
-
CALL {
|
|
134
|
-
WITH element_to_delete, peer
|
|
135
|
+
CALL (element_to_delete, peer) {
|
|
135
136
|
MATCH (element_to_delete)-[r]->(peer)
|
|
136
137
|
WHERE %(branch_filter)s
|
|
137
138
|
RETURN element_to_delete as n1, r as rel_outband1, peer as p1
|
|
@@ -140,7 +141,7 @@ class DeleteElementInSchemaQuery(Query):
|
|
|
140
141
|
}
|
|
141
142
|
WITH n1 as element_to_delete, rel_outband1 as rel_outband, p1 as peer_node
|
|
142
143
|
WHERE rel_outband.status = "active"
|
|
143
|
-
CALL {
|
|
144
|
+
CALL (%(sub_query_out_args)s) {
|
|
144
145
|
%(sub_query_out)s
|
|
145
146
|
}
|
|
146
147
|
WITH p2 as peer_node, rel_outband, element_to_delete
|
|
@@ -150,8 +151,7 @@ class DeleteElementInSchemaQuery(Query):
|
|
|
150
151
|
WITH DISTINCT(element_to_delete) AS element_to_delete
|
|
151
152
|
// Process Inbound Relationship
|
|
152
153
|
MATCH (element_to_delete)<-[]-(peer)
|
|
153
|
-
CALL {
|
|
154
|
-
WITH element_to_delete, peer
|
|
154
|
+
CALL (element_to_delete, peer) {
|
|
155
155
|
MATCH (element_to_delete)<-[r]-(peer)
|
|
156
156
|
WHERE %(branch_filter)s
|
|
157
157
|
RETURN element_to_delete as n1, r as rel_inband1, peer as p1
|
|
@@ -160,7 +160,7 @@ class DeleteElementInSchemaQuery(Query):
|
|
|
160
160
|
}
|
|
161
161
|
WITH n1 as element_to_delete, rel_inband1 as rel_inband, p1 as peer_node
|
|
162
162
|
WHERE rel_inband.status = "active"
|
|
163
|
-
CALL {
|
|
163
|
+
CALL (%(sub_query_in_args)s) {
|
|
164
164
|
%(sub_query_in)s
|
|
165
165
|
}
|
|
166
166
|
WITH p2 as peer_node, rel_inband, element_to_delete
|
|
@@ -172,5 +172,7 @@ class DeleteElementInSchemaQuery(Query):
|
|
|
172
172
|
"branch_filter": branch_filter,
|
|
173
173
|
"sub_query_out": sub_query_out,
|
|
174
174
|
"sub_query_in": sub_query_in,
|
|
175
|
+
"sub_query_out_args": sub_query_out_args,
|
|
176
|
+
"sub_query_in_args": sub_query_in_args,
|
|
175
177
|
}
|
|
176
178
|
self.add_to_query(query)
|
|
@@ -47,7 +47,6 @@ class NodeDuplicateQuery(Query):
|
|
|
47
47
|
@staticmethod
|
|
48
48
|
def _render_sub_query_per_rel_type(rel_name: str, rel_type: str, rel_dir: GraphRelDirection) -> str:
|
|
49
49
|
subquery = [
|
|
50
|
-
f"WITH peer_node, {rel_name}, active_node, new_node",
|
|
51
50
|
f"WITH peer_node, {rel_name}, active_node, new_node",
|
|
52
51
|
f'WHERE type({rel_name}) = "{rel_type}"',
|
|
53
52
|
]
|
|
@@ -81,28 +80,28 @@ class NodeDuplicateQuery(Query):
|
|
|
81
80
|
return "\n".join(subquery)
|
|
82
81
|
|
|
83
82
|
@classmethod
|
|
84
|
-
def _render_sub_query_out(cls) -> str:
|
|
83
|
+
def _render_sub_query_out(cls) -> tuple[str, str]:
|
|
84
|
+
rel_name = "rel_outband"
|
|
85
|
+
sub_query_out_args = f"peer_node, {rel_name}, active_node, new_node"
|
|
85
86
|
sub_queries_out = [
|
|
86
|
-
cls._render_sub_query_per_rel_type(
|
|
87
|
-
rel_name="rel_outband", rel_type=rel_type, rel_dir=GraphRelDirection.OUTBOUND
|
|
88
|
-
)
|
|
87
|
+
cls._render_sub_query_per_rel_type(rel_name=rel_name, rel_type=rel_type, rel_dir=GraphRelDirection.OUTBOUND)
|
|
89
88
|
for rel_type, field_info in GraphNodeRelationships.model_fields.items()
|
|
90
89
|
if field_info.default.direction in (GraphRelDirection.OUTBOUND, GraphRelDirection.EITHER)
|
|
91
90
|
]
|
|
92
91
|
sub_query_out = "\nUNION\n".join(sub_queries_out)
|
|
93
|
-
return sub_query_out
|
|
92
|
+
return sub_query_out, sub_query_out_args
|
|
94
93
|
|
|
95
94
|
@classmethod
|
|
96
|
-
def _render_sub_query_in(cls) -> str:
|
|
95
|
+
def _render_sub_query_in(cls) -> tuple[str, str]:
|
|
96
|
+
rel_name = "rel_inband"
|
|
97
|
+
sub_query_in_args = f"peer_node, {rel_name}, active_node, new_node"
|
|
97
98
|
sub_queries_in = [
|
|
98
|
-
cls._render_sub_query_per_rel_type(
|
|
99
|
-
rel_name="rel_inband", rel_type=rel_type, rel_dir=GraphRelDirection.INBOUND
|
|
100
|
-
)
|
|
99
|
+
cls._render_sub_query_per_rel_type(rel_name=rel_name, rel_type=rel_type, rel_dir=GraphRelDirection.INBOUND)
|
|
101
100
|
for rel_type, field_info in GraphNodeRelationships.model_fields.items()
|
|
102
101
|
if field_info.default.direction in (GraphRelDirection.INBOUND, GraphRelDirection.EITHER)
|
|
103
102
|
]
|
|
104
103
|
sub_query_in = "\nUNION\n".join(sub_queries_in)
|
|
105
|
-
return sub_query_in
|
|
104
|
+
return sub_query_in, sub_query_in_args
|
|
106
105
|
|
|
107
106
|
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
108
107
|
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
|
|
@@ -126,15 +125,14 @@ class NodeDuplicateQuery(Query):
|
|
|
126
125
|
"from": self.at.to_string(),
|
|
127
126
|
}
|
|
128
127
|
|
|
129
|
-
sub_query_out = self._render_sub_query_out()
|
|
130
|
-
sub_query_in = self._render_sub_query_in()
|
|
128
|
+
sub_query_out, sub_query_out_args = self._render_sub_query_out()
|
|
129
|
+
sub_query_in, sub_query_in_args = self._render_sub_query_in()
|
|
131
130
|
|
|
132
131
|
self.add_to_query(self.render_match())
|
|
133
132
|
|
|
134
133
|
# ruff: noqa: E501
|
|
135
134
|
query = """
|
|
136
|
-
CALL {
|
|
137
|
-
WITH node
|
|
135
|
+
CALL (node) {
|
|
138
136
|
MATCH (root:Root)<-[r:IS_PART_OF]-(node)
|
|
139
137
|
WHERE %(branch_filter)s
|
|
140
138
|
RETURN node as n1, r as r1
|
|
@@ -147,8 +145,7 @@ class NodeDuplicateQuery(Query):
|
|
|
147
145
|
WITH active_node, new_node
|
|
148
146
|
// Process Outbound Relationship
|
|
149
147
|
MATCH (active_node)-[]->(peer)
|
|
150
|
-
CALL {
|
|
151
|
-
WITH active_node, peer
|
|
148
|
+
CALL (active_node, peer) {
|
|
152
149
|
MATCH (active_node)-[r]->(peer)
|
|
153
150
|
WHERE %(branch_filter)s
|
|
154
151
|
RETURN active_node as n1, r as rel_outband1, peer as p1
|
|
@@ -157,7 +154,7 @@ class NodeDuplicateQuery(Query):
|
|
|
157
154
|
}
|
|
158
155
|
WITH n1 as active_node, rel_outband1 as rel_outband, p1 as peer_node, new_node
|
|
159
156
|
WHERE rel_outband.status = "active" AND rel_outband.to IS NULL
|
|
160
|
-
CALL {
|
|
157
|
+
CALL (%(sub_query_out_args)s) {
|
|
161
158
|
%(sub_query_out)s
|
|
162
159
|
}
|
|
163
160
|
WITH p2 as peer_node, rel_outband, active_node, new_node
|
|
@@ -167,8 +164,7 @@ class NodeDuplicateQuery(Query):
|
|
|
167
164
|
WITH DISTINCT active_node, new_node
|
|
168
165
|
// Process Inbound Relationship
|
|
169
166
|
MATCH (active_node)<-[]-(peer)
|
|
170
|
-
CALL {
|
|
171
|
-
WITH active_node, peer
|
|
167
|
+
CALL (active_node, peer) {
|
|
172
168
|
MATCH (active_node)<-[r]-(peer)
|
|
173
169
|
WHERE %(branch_filter)s
|
|
174
170
|
RETURN active_node as n1, r as rel_inband1, peer as p1
|
|
@@ -177,7 +173,7 @@ class NodeDuplicateQuery(Query):
|
|
|
177
173
|
}
|
|
178
174
|
WITH n1 as active_node, rel_inband1 as rel_inband, p1 as peer_node, new_node
|
|
179
175
|
WHERE rel_inband.status = "active" AND rel_inband.to IS NULL
|
|
180
|
-
CALL {
|
|
176
|
+
CALL (%(sub_query_in_args)s) {
|
|
181
177
|
%(sub_query_in)s
|
|
182
178
|
}
|
|
183
179
|
WITH p2 as peer_node, rel_inband, active_node, new_node
|
|
@@ -191,5 +187,7 @@ class NodeDuplicateQuery(Query):
|
|
|
191
187
|
"labels": ":".join(self.new_node.labels),
|
|
192
188
|
"sub_query_out": sub_query_out,
|
|
193
189
|
"sub_query_in": sub_query_in,
|
|
190
|
+
"sub_query_out_args": sub_query_out_args,
|
|
191
|
+
"sub_query_in_args": sub_query_in_args,
|
|
194
192
|
}
|
|
195
193
|
self.add_to_query(query)
|
|
@@ -47,7 +47,6 @@ class RelationshipDuplicateQuery(Query):
|
|
|
47
47
|
@staticmethod
|
|
48
48
|
def _render_sub_query_per_rel_type(rel_name: str, rel_type: str, direction: GraphRelDirection) -> str:
|
|
49
49
|
subquery = [
|
|
50
|
-
f"WITH peer_node, {rel_name}, active_rel, new_rel",
|
|
51
50
|
f"WITH peer_node, {rel_name}, active_rel, new_rel",
|
|
52
51
|
f'WHERE type({rel_name}) = "{rel_type}"',
|
|
53
52
|
]
|
|
@@ -61,28 +60,32 @@ class RelationshipDuplicateQuery(Query):
|
|
|
61
60
|
return "\n".join(subquery)
|
|
62
61
|
|
|
63
62
|
@classmethod
|
|
64
|
-
def _render_sub_query_out(cls) -> str:
|
|
63
|
+
def _render_sub_query_out(cls) -> tuple[str, str]:
|
|
64
|
+
rel_name = "rel_outband"
|
|
65
|
+
sub_query_out_args = f"peer_node, {rel_name}, active_rel, new_rel"
|
|
65
66
|
sub_queries_out = [
|
|
66
67
|
cls._render_sub_query_per_rel_type(
|
|
67
|
-
rel_name=
|
|
68
|
+
rel_name=rel_name, rel_type=rel_type, direction=GraphRelDirection.OUTBOUND
|
|
68
69
|
)
|
|
69
70
|
for rel_type, rel_def in GraphRelationshipRelationships.model_fields.items()
|
|
70
71
|
if rel_def.default.direction in [GraphRelDirection.OUTBOUND, GraphRelDirection.EITHER]
|
|
71
72
|
]
|
|
72
73
|
sub_query_out = "\nUNION\n".join(sub_queries_out)
|
|
73
|
-
return sub_query_out
|
|
74
|
+
return sub_query_out, sub_query_out_args
|
|
74
75
|
|
|
75
76
|
@classmethod
|
|
76
|
-
def _render_sub_query_in(cls) -> str:
|
|
77
|
+
def _render_sub_query_in(cls) -> tuple[str, str]:
|
|
78
|
+
rel_name = "rel_inband"
|
|
79
|
+
sub_query_in_args = f"peer_node, {rel_name}, active_rel, new_rel"
|
|
77
80
|
sub_queries_in = [
|
|
78
81
|
cls._render_sub_query_per_rel_type(
|
|
79
|
-
rel_name=
|
|
82
|
+
rel_name=rel_name, rel_type=rel_type, direction=GraphRelDirection.INBOUND
|
|
80
83
|
)
|
|
81
84
|
for rel_type, rel_def in GraphRelationshipRelationships.model_fields.items()
|
|
82
85
|
if rel_def.default.direction in [GraphRelDirection.INBOUND, GraphRelDirection.EITHER]
|
|
83
86
|
]
|
|
84
87
|
sub_query_in = "\nUNION\n".join(sub_queries_in)
|
|
85
|
-
return sub_query_in
|
|
88
|
+
return sub_query_in, sub_query_in_args
|
|
86
89
|
|
|
87
90
|
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
88
91
|
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
|
|
@@ -109,15 +112,14 @@ class RelationshipDuplicateQuery(Query):
|
|
|
109
112
|
"from": self.at.to_string(),
|
|
110
113
|
}
|
|
111
114
|
|
|
112
|
-
sub_query_out = self._render_sub_query_out()
|
|
113
|
-
sub_query_in = self._render_sub_query_in()
|
|
115
|
+
sub_query_out, sub_query_out_args = self._render_sub_query_out()
|
|
116
|
+
sub_query_in, sub_query_in_args = self._render_sub_query_in()
|
|
114
117
|
|
|
115
118
|
self.add_to_query(self.render_match())
|
|
116
119
|
|
|
117
120
|
# ruff: noqa: E501
|
|
118
121
|
query = """
|
|
119
|
-
CALL {
|
|
120
|
-
WITH source, rel, destination
|
|
122
|
+
CALL (source, rel, destination) {
|
|
121
123
|
MATCH path = (source)-[r1:IS_RELATED]-(rel)-[r2:IS_RELATED]-(destination)
|
|
122
124
|
WHERE all(r IN relationships(path) WHERE %(branch_filter)s)
|
|
123
125
|
RETURN rel as rel1, r1 as r11, r2 as r12
|
|
@@ -130,8 +132,7 @@ class RelationshipDuplicateQuery(Query):
|
|
|
130
132
|
WITH DISTINCT(active_rel) as active_rel, new_rel
|
|
131
133
|
// Process Inbound Relationship
|
|
132
134
|
MATCH (active_rel)<-[]-(peer)
|
|
133
|
-
CALL {
|
|
134
|
-
WITH active_rel, peer
|
|
135
|
+
CALL (active_rel, peer) {
|
|
135
136
|
MATCH (active_rel)<-[r]-(peer)
|
|
136
137
|
WHERE %(branch_filter)s
|
|
137
138
|
RETURN active_rel as n1, r as rel_inband1, peer as p1
|
|
@@ -140,7 +141,7 @@ class RelationshipDuplicateQuery(Query):
|
|
|
140
141
|
}
|
|
141
142
|
WITH n1 as active_rel, rel_inband1 as rel_inband, p1 as peer_node, new_rel
|
|
142
143
|
WHERE rel_inband.status = "active"
|
|
143
|
-
CALL {
|
|
144
|
+
CALL (%(sub_query_in_args)s) {
|
|
144
145
|
%(sub_query_in)s
|
|
145
146
|
}
|
|
146
147
|
WITH p2 as peer_node, rel_inband, active_rel, new_rel
|
|
@@ -150,8 +151,7 @@ class RelationshipDuplicateQuery(Query):
|
|
|
150
151
|
WITH DISTINCT(active_rel) as active_rel, new_rel
|
|
151
152
|
// Process Outbound Relationship
|
|
152
153
|
MATCH (active_rel)-[]->(peer)
|
|
153
|
-
CALL {
|
|
154
|
-
WITH active_rel, peer
|
|
154
|
+
CALL (active_rel, peer) {
|
|
155
155
|
MATCH (active_rel)-[r]->(peer)
|
|
156
156
|
WHERE %(branch_filter)s
|
|
157
157
|
RETURN active_rel as n1, r as rel_outband1, peer as p1
|
|
@@ -160,7 +160,7 @@ class RelationshipDuplicateQuery(Query):
|
|
|
160
160
|
}
|
|
161
161
|
WITH n1 as active_rel, rel_outband1 as rel_outband, p1 as peer_node, new_rel
|
|
162
162
|
WHERE rel_outband.status = "active"
|
|
163
|
-
CALL {
|
|
163
|
+
CALL (%(sub_query_out_args)s) {
|
|
164
164
|
%(sub_query_out)s
|
|
165
165
|
}
|
|
166
166
|
WITH p2 as peer_node, rel_outband, active_rel, new_rel
|
|
@@ -172,5 +172,7 @@ class RelationshipDuplicateQuery(Query):
|
|
|
172
172
|
"branch_filter": branch_filter,
|
|
173
173
|
"sub_query_out": sub_query_out,
|
|
174
174
|
"sub_query_in": sub_query_in,
|
|
175
|
+
"sub_query_in_args": sub_query_in_args,
|
|
176
|
+
"sub_query_out_args": sub_query_out_args,
|
|
175
177
|
}
|
|
176
178
|
self.add_to_query(query)
|
|
@@ -50,7 +50,6 @@ class NodeAttributeRemoveMigrationQuery01(AttributeMigrationQuery):
|
|
|
50
50
|
|
|
51
51
|
def render_sub_query_per_rel_type(rel_type: str, rel_def: FieldInfo) -> str:
|
|
52
52
|
subquery = [
|
|
53
|
-
"WITH peer_node, rb, active_attr",
|
|
54
53
|
"WITH peer_node, rb, active_attr",
|
|
55
54
|
f'WHERE type(rb) = "{rel_type}"',
|
|
56
55
|
]
|
|
@@ -75,8 +74,7 @@ class NodeAttributeRemoveMigrationQuery01(AttributeMigrationQuery):
|
|
|
75
74
|
MATCH (node:%(node_kind)s)
|
|
76
75
|
WHERE (size($kinds_to_ignore) = 0 OR NOT any(l IN labels(node) WHERE l IN $kinds_to_ignore))
|
|
77
76
|
AND exists((node)-[:HAS_ATTRIBUTE]-(:Attribute { name: $attr_name }))
|
|
78
|
-
CALL {
|
|
79
|
-
WITH node
|
|
77
|
+
CALL (node) {
|
|
80
78
|
MATCH (root:Root)<-[r:IS_PART_OF]-(node)
|
|
81
79
|
WHERE %(branch_filter)s
|
|
82
80
|
RETURN node as n1, r as r1
|
|
@@ -86,8 +84,7 @@ class NodeAttributeRemoveMigrationQuery01(AttributeMigrationQuery):
|
|
|
86
84
|
WITH n1 as active_node, r1 as rb
|
|
87
85
|
WHERE rb.status = "active"
|
|
88
86
|
// Find all the attributes that need to be updated
|
|
89
|
-
CALL {
|
|
90
|
-
WITH active_node
|
|
87
|
+
CALL (active_node) {
|
|
91
88
|
MATCH (active_node)-[r:HAS_ATTRIBUTE]-(attr:Attribute { name: $attr_name })
|
|
92
89
|
WHERE %(branch_filter)s
|
|
93
90
|
RETURN active_node as n1, r as r1, attr as attr1
|
|
@@ -98,8 +95,7 @@ class NodeAttributeRemoveMigrationQuery01(AttributeMigrationQuery):
|
|
|
98
95
|
WHERE rb.status = "active"
|
|
99
96
|
WITH active_attr
|
|
100
97
|
MATCH (active_attr)-[]-(peer)
|
|
101
|
-
CALL {
|
|
102
|
-
WITH active_attr, peer
|
|
98
|
+
CALL (active_attr, peer) {
|
|
103
99
|
MATCH (active_attr)-[r]-(peer)
|
|
104
100
|
WHERE %(branch_filter)s
|
|
105
101
|
RETURN active_attr as a1, r as r1, peer as p1
|
|
@@ -108,7 +104,7 @@ class NodeAttributeRemoveMigrationQuery01(AttributeMigrationQuery):
|
|
|
108
104
|
}
|
|
109
105
|
WITH a1 as active_attr, r1 as rb, p1 as peer_node
|
|
110
106
|
WHERE rb.status = "active"
|
|
111
|
-
CALL {
|
|
107
|
+
CALL (peer_node, rb, active_attr) {
|
|
112
108
|
%(sub_query_all)s
|
|
113
109
|
}
|
|
114
110
|
WITH p2 as peer_node, rb, active_attr
|
|
@@ -21,7 +21,6 @@ class NodeRemoveMigrationBaseQuery(MigrationQuery):
|
|
|
21
21
|
rel_def: FieldInfo,
|
|
22
22
|
) -> str:
|
|
23
23
|
subquery = [
|
|
24
|
-
f"WITH peer_node, {rel_name}, active_node",
|
|
25
24
|
f"WITH peer_node, {rel_name}, active_node",
|
|
26
25
|
f'WHERE type({rel_name}) = "{rel_type}"',
|
|
27
26
|
]
|
|
@@ -63,8 +62,7 @@ class NodeRemoveMigrationBaseQuery(MigrationQuery):
|
|
|
63
62
|
query = """
|
|
64
63
|
// Find all the active nodes
|
|
65
64
|
MATCH (node:%(node_kind)s)
|
|
66
|
-
CALL {
|
|
67
|
-
WITH node
|
|
65
|
+
CALL (node) {
|
|
68
66
|
MATCH (root:Root)<-[r:IS_PART_OF]-(node)
|
|
69
67
|
WHERE %(branch_filter)s
|
|
70
68
|
RETURN node as n1, r as r1
|
|
@@ -91,13 +89,12 @@ class NodeRemoveMigrationQueryIn(NodeRemoveMigrationBaseQuery):
|
|
|
91
89
|
insert_return: bool = False
|
|
92
90
|
|
|
93
91
|
def render_node_remove_query(self, branch_filter: str) -> str:
|
|
94
|
-
sub_query = self.render_sub_query_in()
|
|
92
|
+
sub_query, sub_query_args = self.render_sub_query_in()
|
|
95
93
|
query = """
|
|
96
94
|
// Process Inbound Relationship
|
|
97
95
|
WITH active_node
|
|
98
96
|
MATCH (active_node)<-[]-(peer)
|
|
99
|
-
CALL {
|
|
100
|
-
WITH active_node, peer
|
|
97
|
+
CALL (active_node, peer) {
|
|
101
98
|
MATCH (active_node)-[r]->(peer)
|
|
102
99
|
WHERE %(branch_filter)s
|
|
103
100
|
RETURN active_node as n1, r as rel_inband1, peer as p1
|
|
@@ -106,27 +103,29 @@ class NodeRemoveMigrationQueryIn(NodeRemoveMigrationBaseQuery):
|
|
|
106
103
|
}
|
|
107
104
|
WITH n1 as active_node, rel_inband1 as rel_inband, p1 as peer_node
|
|
108
105
|
WHERE rel_inband.status = "active"
|
|
109
|
-
CALL {
|
|
106
|
+
CALL (%(sub_query_args)s) {
|
|
110
107
|
%(sub_query)s
|
|
111
108
|
}
|
|
112
109
|
WITH p2 as peer_node, rel_inband, active_node
|
|
113
110
|
FOREACH (i in CASE WHEN rel_inband.branch IN ["-global-", $branch] THEN [1] ELSE [] END |
|
|
114
111
|
SET rel_inband.to = $current_time
|
|
115
112
|
)
|
|
116
|
-
""" % {"sub_query": sub_query, "branch_filter": branch_filter}
|
|
113
|
+
""" % {"sub_query": sub_query, "sub_query_args": sub_query_args, "branch_filter": branch_filter}
|
|
117
114
|
return query
|
|
118
115
|
|
|
119
|
-
def render_sub_query_in(self) -> str:
|
|
116
|
+
def render_sub_query_in(self) -> tuple[str, str]:
|
|
117
|
+
rel_name = "rel_inband"
|
|
118
|
+
sub_query_in_args = f"peer_node, {rel_name}, active_node"
|
|
120
119
|
sub_queries_in = [
|
|
121
120
|
self.render_sub_query_per_rel_type(
|
|
122
|
-
rel_name=
|
|
121
|
+
rel_name=rel_name,
|
|
123
122
|
rel_type=rel_type,
|
|
124
123
|
rel_def=rel_def,
|
|
125
124
|
)
|
|
126
125
|
for rel_type, rel_def in GraphNodeRelationships.model_fields.items()
|
|
127
126
|
]
|
|
128
127
|
sub_query_in = "\nUNION\n".join(sub_queries_in)
|
|
129
|
-
return sub_query_in
|
|
128
|
+
return sub_query_in, sub_query_in_args
|
|
130
129
|
|
|
131
130
|
def get_nbr_migrations_executed(self) -> int:
|
|
132
131
|
return 0
|
|
@@ -137,13 +136,12 @@ class NodeRemoveMigrationQueryOut(NodeRemoveMigrationBaseQuery):
|
|
|
137
136
|
insert_return: bool = False
|
|
138
137
|
|
|
139
138
|
def render_node_remove_query(self, branch_filter: str) -> str:
|
|
140
|
-
sub_query = self.render_sub_query_out()
|
|
139
|
+
sub_query, sub_query_args = self.render_sub_query_out()
|
|
141
140
|
query = """
|
|
142
141
|
// Process Outbound Relationship
|
|
143
142
|
WITH active_node
|
|
144
143
|
MATCH (active_node)-[]->(peer)
|
|
145
|
-
CALL {
|
|
146
|
-
WITH active_node, peer
|
|
144
|
+
CALL (active_node, peer) {
|
|
147
145
|
MATCH (active_node)-[r]->(peer)
|
|
148
146
|
WHERE %(branch_filter)s
|
|
149
147
|
RETURN active_node as n1, r as rel_outband1, peer as p1
|
|
@@ -152,27 +150,29 @@ class NodeRemoveMigrationQueryOut(NodeRemoveMigrationBaseQuery):
|
|
|
152
150
|
}
|
|
153
151
|
WITH n1 as active_node, rel_outband1 as rel_outband, p1 as peer_node
|
|
154
152
|
WHERE rel_outband.status = "active"
|
|
155
|
-
CALL {
|
|
153
|
+
CALL (%(sub_query_args)s) {
|
|
156
154
|
%(sub_query)s
|
|
157
155
|
}
|
|
158
156
|
FOREACH (i in CASE WHEN rel_outband.branch IN ["-global-", $branch] THEN [1] ELSE [] END |
|
|
159
157
|
SET rel_outband.to = $current_time
|
|
160
158
|
)
|
|
161
|
-
""" % {"sub_query": sub_query, "branch_filter": branch_filter}
|
|
159
|
+
""" % {"sub_query": sub_query, "sub_query_args": sub_query_args, "branch_filter": branch_filter}
|
|
162
160
|
|
|
163
161
|
return query
|
|
164
162
|
|
|
165
|
-
def render_sub_query_out(self) -> str:
|
|
163
|
+
def render_sub_query_out(self) -> tuple[str, str]:
|
|
164
|
+
rel_name = "rel_outband"
|
|
165
|
+
sub_query_out_args = f"peer_node, {rel_name}, active_node"
|
|
166
166
|
sub_queries_out = [
|
|
167
167
|
self.render_sub_query_per_rel_type(
|
|
168
|
-
rel_name=
|
|
168
|
+
rel_name=rel_name,
|
|
169
169
|
rel_type=rel_type,
|
|
170
170
|
rel_def=rel_def,
|
|
171
171
|
)
|
|
172
172
|
for rel_type, rel_def in GraphNodeRelationships.model_fields.items()
|
|
173
173
|
]
|
|
174
174
|
sub_query_out = "\nUNION\n".join(sub_queries_out)
|
|
175
|
-
return sub_query_out
|
|
175
|
+
return sub_query_out, sub_query_out_args
|
|
176
176
|
|
|
177
177
|
def get_nbr_migrations_executed(self) -> int:
|
|
178
178
|
return self.num_of_results
|
infrahub/core/models.py
CHANGED
|
@@ -20,6 +20,7 @@ if TYPE_CHECKING:
|
|
|
20
20
|
from infrahub.core.schema.schema_branch import SchemaBranch
|
|
21
21
|
|
|
22
22
|
GENERIC_ATTRIBUTES_TO_IGNORE = ["namespace", "name", "branch"]
|
|
23
|
+
PROPERTY_NAMES_TO_IGNORE = ["regex", "min_length", "max_length"]
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
class NodeKind(BaseModel):
|
|
@@ -252,11 +253,37 @@ class SchemaUpdateValidationResult(BaseModel):
|
|
|
252
253
|
if not sub_field_diff:
|
|
253
254
|
raise ValueError("sub_field_diff must be defined, unexpected situation")
|
|
254
255
|
|
|
255
|
-
for prop_name in sub_field_diff.changed:
|
|
256
|
+
for prop_name, prop_diff in sub_field_diff.changed.items():
|
|
257
|
+
if prop_name in PROPERTY_NAMES_TO_IGNORE:
|
|
258
|
+
continue
|
|
259
|
+
|
|
256
260
|
field_info = field.model_fields[prop_name]
|
|
257
261
|
field_update = str(field_info.json_schema_extra.get("update")) # type: ignore[union-attr]
|
|
258
262
|
|
|
259
|
-
|
|
263
|
+
if isinstance(prop_diff, HashableModelDiff):
|
|
264
|
+
for param_field_name in prop_diff.changed:
|
|
265
|
+
# override field_update if this field has its own json_schema_extra.update
|
|
266
|
+
try:
|
|
267
|
+
prop_field = getattr(field, prop_name)
|
|
268
|
+
param_field_info = prop_field.model_fields[param_field_name]
|
|
269
|
+
param_field_update = str(param_field_info.json_schema_extra.get("update"))
|
|
270
|
+
except (AttributeError, KeyError):
|
|
271
|
+
param_field_update = None
|
|
272
|
+
|
|
273
|
+
schema_path = SchemaPath(
|
|
274
|
+
schema_kind=schema.kind,
|
|
275
|
+
path_type=path_type,
|
|
276
|
+
field_name=field_name,
|
|
277
|
+
property_name=f"{prop_name}.{param_field_name}",
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
self._process_field(
|
|
281
|
+
schema_path=schema_path,
|
|
282
|
+
field_update=param_field_update or field_update,
|
|
283
|
+
)
|
|
284
|
+
continue
|
|
285
|
+
|
|
286
|
+
schema_path = SchemaPath(
|
|
260
287
|
schema_kind=schema.kind,
|
|
261
288
|
path_type=path_type,
|
|
262
289
|
field_name=field_name,
|